J2EE資源管理常見策略總結


公所周知J2EE底層是多線程的,無論何種資源管理的策略都是與線程相關的,因此通過合理的資源管理來應對多線程的環境是非常關鍵的。下面就我所知道的,總結如下:

第一種:實例池

   實例池管理策略就是通過將我們的業務組件的實例保存到池中,這樣可以達到重用的目的。說到實例池,需要明確一下單線程模型的概念,所謂單線程模型就是一個實例在某一時間只能服務於同一個線程,單線程模型使得無狀態的業務組件不需要關注復雜的線程問題(通俗點講,單線程模型使得業務開發人員可以采用不需要顯示的同步機制來編寫業務組件代碼,但是業務組件可以安全的運行與多線程環境之下)。如果采用實例池將有助於實現單線程模型。比如EJB對於無狀態的會話bean的管理就采取的是實例池的管理策略,這樣以來我們的SLSB中是不需要同步的(這也是為什么EJB組件中不能有顯示的同步代碼的原因,因為EJB本來就是單線程的模型),從而減輕了業務開發人員的負擔。   下面總結一下這種方法的優缺點:

優點:

 1 采用實例池可以使得無狀態的業務組件不需要同步,這樣就減輕了業務開發人員的負擔。  2. 采用實例池可以限制並發執行的線程的數量,當實例池沒有可用的實例可用時,線程就需要掛起,這樣防止大的並發對服務器造成的壓力。

缺點:

 1 因為采用了實例池,增加了管理實例池的開銷,增加了系統的復雜性。  2 采用實例池還是沒有從根本上解決線程的問題,因為雖然實例池的實例不用同步,但是實例池的實例需要其它的組件來協作,這樣其它組件的實例還是需要同步的。  

具體的應用:

EJB的無狀態會話bean,數據庫連接池技術,TCP連接技術,web容器和ejb容器的線程池等。     PS:面向模式的軟件體系結構-卷3對“實例池”有詳細的描述。    

第二種:容器管理的單例 

  目前各種IOC容器一般都采取了此種概念,系統只維護一個無狀態業務組件的實例。比如目前流行的IOC容器(spring,Picocontainer等),它們都有將業務組件設置為單例的功能。這樣以來減輕了維護實例池的開銷,並且通過容器可以管理組件的生命周期,不是像以前那樣用完了就丟給垃圾收集器,從而減輕了一些復雜的初始化的開銷。   下面是此種方式的優缺點:

 優點:

1. 減輕了一些需要復雜初始化的實例創建開銷,從而提高了系統性能。 2. 通過IOC進行了組件的生命周期管理,減低了開發人員的負擔。  

 缺點:

需要我們業務人員確保每個實例是無狀態的,如果業務組件是有狀態的,那么就要進行顯示的同步,而多線程編程不是每個業務開發人員都能勝任的。 2  任意多的線程都可以進行並發調用,這樣以來服務器也許無法應對巨大的負載而崩潰。  

具體的應用:

目前的Servlet規范就采用一個實例(拋棄了以前的servlet單線程模型)來服務於多線程調用,這樣我們必須確保servlet內部的線程安全性。 各種IOC容器(spring,Picocontainer等)  

第三種:每個session一個實例

在開發過程中,我們的業務狀態如何保存?這就涉及到了業務狀態管理的問題,那么我們就可以采取每個session一個實例來進行,比如httpsession,但是在當今的分層架構下,用httpsession來保存業務狀態是有缺點的,首先導致了業務狀態泄露到了表現層,不利於層的內聚性,並且httpsession中保存的狀態太大的話,會造成內存浪費太多。另外還有就是EJB中的statefull session bean,也采取了這種模式,每個有狀態的會話bean只為一個客戶服務,並且好的一點是statefull session bean支持鈍化技術,並且它還支持完整的事務語義,所以它將業務狀態的管理和事務結合了起來,這一點是比較好的,唯一不好的地方就是因為EJB是組件,要想運行必須要結合容器才行。  

具體的應用:

Web中的httpsession,以及EJB中statefull session bean   

第四種:每個請求一個實例

   每個請求一個實例也是一種比較常用的方式,對於一些初始化不是很復雜的實例,我們就可以采用這種方法。采用這種方式得力與JVM性能的改進,在以前垃圾收集器算法還不成熟的時候,如果采用這種方式將會對系統性能產生很大的影響。但是現在垃圾收集器算法優化已經抵消了一定的開銷。比如表現層框架webwork、struts2,它們的xwork內核就是在每個請求過來,都新建一個命令實例(action),目前也沒有出現嚴重的性能問題。   下面總結一下此種方式的優缺點:

優點:

因為是每個請求(也就是每個線程)一個實例,那么業務開發人員就不需要對業務對象進行顯示的同步,這樣減輕了業務開發人員的負擔。   

缺點:  

對於一些需要復雜初始化的實例,這樣會給系統性能帶來負面的影響。  

具體的應用:

Webwork以及struts2的action都采取如此的策略,以及spring框架的prototype方式。    

第五種:ThreadLocal策略

此種策略在J2EE中也是比較常用的。它是以線程管理來驅動我們的資源管理的方式,每個線程都獨自保存面向自己的變量,這樣以來就可以避免多線程訪問造成對共享變量的破壞。比如hibernate中,當我們采用JDBC事務的時候,配置hibernate.current_session_context_class=thread,內部就將當前的session與線程綁定,這樣以來在同一個線程中操作將是當前綁定的session。還比如webwork中對於ActionContext的管理也采取了Treadlocal的策略,這樣以來ActionContext(action的執行上下文)就與當前線程綁定(具體實現是采用一個ActionContext內部類來實現,以前看的源代碼,記得不是很清楚了。。),避免多線程訪問帶來的復雜性。     以上的各種策略看起來是資源管理的策略,但是它們都是與多線程環境有密切關系的,每一種都有自己的優點和缺點,雖然目前框架已經為我們做好了資源管理工作,但是理解它們管理的方式對於業務開發人員還是大有裨益的。以上這些策略也是目前J2EE中常用的,不能確定那個方案比較好,具體的問題具體分析才是上上策。

本文出自 “仁義禮智信” 博客,請務必保留此出處http://yuquan.blog.51cto.com/1924539/360721


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com