單例會話bean(2)----生命週期回調與併發性

生命週期回調

在生命週期回調方面單例會話bean與無狀態會話bean在大體上是一樣的,都擁有下面兩個回調PostConstructPreDestroy。這連個回調分別是容器在服務器初始化bean實例之後以及釋放bean實例之前調用。對於單例會話bean來說PostConstruct只會調用一次,而PreDestroy僅當應用程序整個關閉時纔會調用,因此它也只會被調用一次,而無狀態會話bean的這兩個生命週期回調在創建和銷燬bean實例時則需要經常被調用。

單例併發性

由於單例會話bean的特殊性(有且僅有一個實例),所以併發性是單例會話bean不得不考慮的問題。對於單例會話bean來說它可以使用容器託管(container-managed)的併發性或bean託管(bean-managed)的併發性(concurrency)。當然默認是容器託管的,(容器大部分情況下認爲使用者是“懶惰”+“白癡”)這相當於在所有業務方法之上的寫鎖定(write lock)這就使得所有業務方法的調用均被序列化,因此在任何時間內只有一個客戶端可以訪問bean。(在處理同步問題的時候各個服務器廠商有着自己的方法再次不在敘述。)

當然,對於單例會話bean來說並非所有業務方法都是爲了更改bean的狀態(筆者更偏向於理解成bean中的各個屬性)。那些不能更改bean狀態的業務方法(比如getter方法)是希望杯允許以並行方式運行的,這時@LockLockType.READ)註解可以用來聲明這種訪問是安全的,是可以並行訪問的。

@Singleton
public class HitCounter {
	int count;

	public void increment() { ++count; }
	
	@Lock(LockType.READ)
	public int getCount() { return count; }

    public void reset() { count = 0; }
}

上面的代碼顯示了覆蓋業務方法鎖定語義HitCounter bean。這種情況下,getCount()方法標記爲@LockLockType.READ),表明多個客戶端可以安全地併發執行該方法。剩餘的方法仍然是默認@LockLockType.WRITE),容器將確定讀取和寫入方法調用是互斥的。

容器是固定的,如果開發人員希望能夠更加細粒度地控制併發性,那麼應該把單例會話bean配置爲使用bean託管的併發性,這其實很簡單只需要在bean類上添加@Concurrency ManagementConcurrencyManagementtype.BEAN)註解就可以了。這時將禁用容器託管的併發性,@Lock註解就失去了作用。此時開發人員就可以決定使用合適的Java併發機制來確保數據安全了。

開發速度和細粒度控制是一對矛盾,在許多情況下,bean託管的併發性比容器託管的併發性更好(這取決於開發人員的水平)。細粒度的控制併發性將產生更好的性能,而使用容器託管的併發性時,所有業務方法都將與某種鎖定相關,無論是否涉及狀態操作,所以性能上會有差距。簡而言之如果開發階段想節省時間那麼就老老實實用容器託管,如果想細粒度維護併發性那麼就自己寫,如果考慮後期維護成本就用容器託管,如果擔心以後系統出現併發性能問題那就自己寫,……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章