摘要:Java 2 Standard Edtion 5.0(代號Tiger)是Sun Microsystems公司最新發布的Java2平臺標準版。在J2SE5.0中提供了java.util.concurrent包。這個包實現了JSR166中描述的并發編程(concurrent programming)模型。
本課題中將通過使用J2SE5.0中的concurrent包實現一個標準的對象池來對J2SE5.0并發控制效率進行研究,并將實現的對象池應用在Web程序當中,構建一個擴展Struts框架的Web程序框架。
本文分兩個個主要部分講解。第一部分講述了開發對象池及Web框架鎖必備的知識,重點講述Java語言及UML建模;第二部分講述了對象池組件的系統設計,包括需求分析,組件設計等。
關鍵詞:對象池 UML建模 Sturts框架
1 基本理論
1.1 Java語言簡介
Java是1995年6月由Sun Microsystems公司提出的一種革命化語言,與其他編程語一樣,這種語言在短時間內即得到了迅速的發展。由于具有易用性、平臺無關性、易移植性等諸多特征,這門語言得到了廣泛的應用。而且,這種語言具有很好的發展前景:程序開發費用少,工作效率高,并擁有很好的用戶界面和強大的開發工具。網上數據編程體現得非常充分,是其它語言無法做到的。
1.2 UML技術
1.2.1 UML簡介
統一建模語言(UML)是一個通用的可視化建模語言,用于對軟件進行描述、可視化處理、構造和建立軟件系統制品的文檔。它記錄了對必須構造的系統的決定和理解,可用于對系統的理解、設計、瀏覽、配置、維護和信息控制。
UML描述了一個系統的靜態結構和動態行為。UML將系統描述為一些離散的相互作用的對象,并最終為外部用戶提供一定的功能的模型結構。靜態結構定義了系統中的重要對象的屬性和操作,以及這些對象之間的相互關系。動態行為定義了對象的時間特性和對象為完成目標而相互進行通信的機制。從不同但相互聯系的角度對系統建立的模型可用與不同的目的。
1.2.2 UML圖
1.2.2.1 類圖
類圖表示不同的實體(人、事物和數據)如何彼此相關,換句話說,它顯示了系統的靜態結構。類圖可用于表示邏輯類,邏輯類通常就是業務人員所談及的事物種類——搖滾樂隊、CD、廣播劇;或者貸款、住房抵押、汽車信貸以及利率。類圖還可用于表示實現類,實現類就是程序員處理的實體。實現類圖或許會與邏輯類圖顯示一些相同的類。然而,實現類圖不會使用相同的屬性來描述,因為它很可能具有對諸如Vector和HashMap這種事物的引用。
1.2.2.2 狀態圖
狀態圖表示某個類所處的不同狀態和該類的狀態轉換信息。有人可能會爭論說每個類都有狀態,但不是每個類都應該有一個狀態圖。只對“感興趣的”狀態的類(也就是說,在系統活動期間具有三個或更多潛在狀態的類)才進行狀態圖描述。
1.2.2.3 活動圖
活動圖表示在處理某個活動時兩個或者更多類對象之間的過程控制流。活動圖可用于在業務單元的級別上對更高級別的業務過程進行建模,或者對低級別的內部類操作進行建模。根據我的經驗,活動圖最適合用于對較高級別的過程建模,比如公司當前在如何運作業務,或者業務如何運作等。這是因為與序列圖相比,活動圖在表示上“不夠技術性”,但有業務頭腦的人們往往能夠更快速地理解它們。
1.2.2.4 序列圖
序列圖顯示具體用例(或者是用例的一部分)的詳細流程。它幾乎是自描述的,并且顯示了流程中不同對象之間的調用關系,同時還可以很詳細地顯示對不同對象的不同調用。
序列圖有兩個維度:垂直維度以發生的時間順序顯示消息/調用的序列;水平維度顯示消息被發送到的對象實例。
1.2.2.5 組件圖
組件圖提供系統的物理視圖。它的用途是顯示系統中的軟件對其他軟件組件(例如,庫函數)的依賴關系。
1.2.2.6 用例圖
用例圖描述了系統提供的一個功能單元。用例圖的主要目的是幫助開發團隊以一種可視化的方式理解系統的功能需求,包括基于基本流程的“角色”(actors,也就是與系統交互的其他實體)關系,以及系統內用例之間的關系。用例圖一般表示出用例的組織關系——要么是整個系統的全部用例,要么是完成具體功能(例如所有安全管理相關的用例)的一組用例。要在用例圖上顯示某個用例,可繪制一個橢圓,然后將用例的名稱放在橢圓的中心或橢圓下面的中間位置;要在用例圖上繪制一個角色(表示一個系統用戶),可繪制一個人形符號。角色和用例之間的關系使用簡單的線段來描述。
1.2.2.7 部署圖
部署圖表示該軟件系統如何部署到硬件環境中。它的用途是顯示該系統不同的組件將在何處物理地運行,以及它們將如何彼此通信。因為部署圖是對物理運行情況進行建模,系統的生產人員就可以很好地利用這種圖。
1.3 開發工具Eclipse
Eclipse是一個開放源代碼的、基于Java的可擴展開發平臺。就其本身而言,它只是一個框架和一組服務,用于通過插件組件構建開發環境。Eclipse本身附帶了一個標準的插件集,包括Java開發工具(Java Development Tools,JDT)。
Eclipse是一個很讓人著迷的開發環境,它提供的核心框架和可擴展的插件機制給廣大的程序員提供了無限的想象和創造空間。目前網上流傳相當豐富且全面的開發工具方面的插件,但是Eclipse已經超越了開發環境的概念,可以想象Eclipse將成為未來的集成的桌面環境。目前的Eclipse本身就具備資源管理和外部程序的功能,加上無所不能的插件,將構成一個豐富多彩的工作環境而不僅僅是一個IDE。
2 對象池組件分析與概要設計
2.1 概要
恰當地使用對象池化技術,可以有效地減少對象生成和初始化時的消耗,提高系統的運行效率。
對象池化的基本思路是:將用過的對象保存起來,等下一次需要這種對象的時候,再拿出來重復使用,從而在一定程度上減少頻繁創建對象所造成的開銷。用于充當保存對象的“容器”的對象,被稱為“對象池”(Object Pool,或簡稱Pool)。
對于沒有狀態的對象(例如String),在重復使用之前,無需進行任何處理;對于有狀態的對象(例如StringBuffer),在重復使用之前,就需要把它們恢復到等同于剛剛生成時的狀態。由于條件的限制,恢復某個對象的狀態的操作不可能實現了的話,就得把這個對象拋棄,改用新創建的實例了。
并非所有對象都適合拿來池化——因為維護對象池也要造成一定開銷。對生成時開銷不大的對象進行池化,反而可能會出現“維護對象池的開銷”大于“生成新對象的開銷”,從而使性能降低的情況。但是對于生成時開銷可觀的對象,池化技術就是提高性能的有效策略了。

2.2 需求分析
2.2.1 對象池組件功能需求
對象池為客戶線程提供取得對象的方法getObject,歸還對象的方法releaseObject和銷毀對象的方法invalidateObject。
圖1 是客戶線程從池中取對象時的序列圖,當客戶線程取對象時對象池根據情況去從池中取對象或調用Factory創建一個對象。在取對象同時對象持還會根據設置調用Factory對對象進行檢查,激活或狀態復原。

圖2是客戶線程將對象送回對象池中時的序列圖,當客戶線程送回對象到對象池時。在取對象同時對象池還會根據設置調用Factory對對象進行檢查和狀態復原。
圖3是客戶進程銷毀一個對象時的序列圖。當客戶線程銷毀對象時,對象池將調用Factory的destroyObject方法將對象破壞掉。
2.2.2 對象池(ObjectPool)組件性能需求
對對象池的要求如下:
1) 對象池組件運行在多線程環境下,要考慮對象池的線程安全性;
2) 對象池提供三種(increasing,bloking,blockingtimeout)取得對象的方法;
3) 對象池在創建時對其初始化,并可以在對象池運行過程中可以修改運行參數;
4) 在對象池內部使用泛型(Generics)技術為各種類型對象構造一個通用的pool。
2.3 開發環境配置
2.3.1 硬件環境
2.3.2 軟件環境
1) 開發環境
2) 運行環境

2.4 系統設計
2.4.1 對象池(ObjectPool)組件
創建PoolableObjectFactory接口,使開發人員通過實現該接口將指定對象池化;創建一個PoolableObjectFactory接口基類,在接口的實現中也可以繼承該基類以節省開發量。
創建一個通用的對象池CommonObjectPool類,該類通過調用PoolableObjectFactory接口可以實現對象的池化,從池中取對象,將對象歸還到池中,檢驗和銷毀一個對象的功能。
在實現CommonObjectPool時需要考慮代碼的線程安全性,以保證對象池的健壯性和效率。
2.4.2 對象池組件UML圖
對象池組件的類圖如圖4,其中:
接口ObjectPool中定義了開發人員使用對象池時可用的接口。
BaseObjectPool類是對接口ObjectPool的一個基本實現,開發者可以通過繼承這個實現來創建自己所需的特定功能的對象池。
CommonObjectPool是我們創建的一個通用的對象池組件,它繼承了BaseObject,該組件滿足了以上我們的對象池組件開發要求。該類的各個屬性和方法定義如下:
屬性:
a. MaxActivate:最大活躍對象數目,在非INCREASE型對象池中決定了最多可以使用的對象的數目。如果小于零則為無限。
b. MaxIdle:最大空閑數,控制對象池中最多有多少個空閑對象;該屬性也決定了對象池容器的大小。
c. MinIdle:最小空閑數,保持對象池中最少的空閑對象數量。
d. 最大活動數MaxActivate:最多可提供的對象數目。
e. PoolTYPE {INCREASE,BLOCK,TIMEOUT}:對象池類型。分為:INCREASE(對象池空時可以繼續創建對象);BLOCK(對象池空時阻塞調用線程,拋出異常);TIMEOUT(對象池空時,阻塞對象一段時間,直到超時拋出超時異常)。
f. MaxWaitTime:設置超時類型時,線程每次等待的時間。
g. MaxWait:超時等待時等待線程的最大數目。
h. NumWhileEvict:設置evictor執行時需要檢測對象的數目。
i. CheckWhileIdle:標示是否校驗對象池中空閑的對象。
j. TestOnGet:從池中取對象時是否需要校驗對象。
k. TestOnRelease:向池中歸還對象時是否需要校驗對象。
l. TimeOutOnEvict:Evictor檢測對象池時,池中對象的生命周期。
方法:
a. getObject:從對象池中取得一個對象。
b. releaseObject:將一個對象歸還到對象持中。
c. ivalidateObject:將取出的對象銷毀。
d. clean:清空對象池。
e. close:關閉對象池。
f. evict:對池中的對象進行檢測,將過期對象破壞掉。
g. addObjectToPool:向池中加入對象。
h. addObject:新建一個對象放入池中。
i. ensureMinIdle:確保池中對象數目的最小值。
j. startEvictor:啟動后臺維護線程。
PoolableObjectFactory是可池化對象的接口,開發者可以通過實現該接口使得指定對象被對象池進行池化。
BasePoolableObjectFactory是PoolableObjectFactory接口的一個簡單實現,開發者可以通過繼承該類來池化特定的對象。
Evictor是CommonObjectPool中的內部線程類,該類負責創建一個后臺維護進程以保證對象池的正常運行。
TimeStampPair是CommonObjectPool中的內部線程類,它是為存放對象并記錄對象時間信息的。
結束語
通過利用J2SE5.0提供的新特性實現對象池CommonObjectPool及其在Web應用程序中的應用,我們不僅對對象持技術有了很深的了解,而且在性能的測試與比較中對J2SE5.0對并發控制效率的提高有了一定的驗證。
盡管我們的CommonObjectPool只是個試驗中的組件,擴展的Struts框架還有一些不足,但是其應用前景還是相當看好的。經過對我們的擴展框架的進一步完善,我相信開發人員能夠基于該框架輕松地開發出穩定性好效率高的Web應用程序。
參考文獻:
[1]Doug Lea.Java并發編程-設計原則與模式(第二版).中國電力出版社,2003-10-1.
[2][美]格蘭德.Java企業設計模式.電子工業出版社,2003-8-1.
[3]Paul Hyde.Java線程編程.人民郵電出版社,2003-11-1.
[4]Bruce Eckel.Java 編程思想.機械工業出版社,2002-8-9.
[5][美]布拉德利.Java程序設計教程.電子工業出版社,2003-7-1.
[6]李云山.深入淺出Java語言程序設計.中國青年出版社,2003-9-1.
[7]孫衛琴.Tomcat與Java Web開發技術詳解.電子工業出版社,2004-8-1.
[8]邵維忠.UML用戶指南.機械工業出版社,2001-6-1.
[9]王行言.Java語言與面向對象程序設計.清華大學出版社,2000-9-1.