事件監(jiān)聽的安全性
如下代碼,在用Vector進(jìn)行不安全的迭代時,另外一個線程對Vector的對象進(jìn)行添加或刪除時,會拋出會拋出 ConcurrentModificationException異常。
Vector<Listener> v;
for (int i=0; i<v.size(); i++)
v.get(i).eventHappened(event);
java.util.concurrent 中的 CopyOnWriteArrayList 類,能夠幫助防止這個問題。它實(shí)現(xiàn)了 List,而且是線程安全的,但是它的迭代器不會拋出 ConcurrentModificationException,遍歷期間也不要求額外的鎖定。這種特性組合是通過在每次列表修改時,在內(nèi)部重新分配并拷貝列表內(nèi)容而實(shí)現(xiàn)的,這樣,遍歷內(nèi)容的線程不需要處理變化 —— 從它們的角度來說,列表的內(nèi)容在遍歷期間保持不變。雖然這聽起來可能沒效率,但是請記住,在多數(shù)觀察者情況下,每個組件只有少量偵聽器,遍歷的數(shù)量遠(yuǎn)遠(yuǎn)超過插入和刪除的數(shù)量。所以更快的迭代可以補(bǔ)償較慢的變化過程,并提供更好的并發(fā)性,因?yàn)槎鄠€線程可以同時迭代列表。
事件監(jiān)聽初使化風(fēng)險
事件監(jiān)聽器允許"this"轉(zhuǎn)義
失效的監(jiān)聽
public void processFile(String filename) throws IOException {
cancelButton.registerListener(this);
// open file, read it, process it
// might throw IOException
cancelButton.unregisterListener(this);
}
當(dāng)讀入文件時,產(chǎn)生異常,會造成取消注冊事件不能被執(zhí)行,取消登記的操作應(yīng)當(dāng)在 finally 塊中進(jìn)行,這樣,processFile() 方法的所有出口都會執(zhí)行它。
如下代碼,在用Vector進(jìn)行不安全的迭代時,另外一個線程對Vector的對象進(jìn)行添加或刪除時,會拋出會拋出 ConcurrentModificationException異常。
Vector<Listener> v;
for (int i=0; i<v.size(); i++)
v.get(i).eventHappened(event);
java.util.concurrent 中的 CopyOnWriteArrayList 類,能夠幫助防止這個問題。它實(shí)現(xiàn)了 List,而且是線程安全的,但是它的迭代器不會拋出 ConcurrentModificationException,遍歷期間也不要求額外的鎖定。這種特性組合是通過在每次列表修改時,在內(nèi)部重新分配并拷貝列表內(nèi)容而實(shí)現(xiàn)的,這樣,遍歷內(nèi)容的線程不需要處理變化 —— 從它們的角度來說,列表的內(nèi)容在遍歷期間保持不變。雖然這聽起來可能沒效率,但是請記住,在多數(shù)觀察者情況下,每個組件只有少量偵聽器,遍歷的數(shù)量遠(yuǎn)遠(yuǎn)超過插入和刪除的數(shù)量。所以更快的迭代可以補(bǔ)償較慢的變化過程,并提供更好的并發(fā)性,因?yàn)槎鄠€線程可以同時迭代列表。
事件監(jiān)聽初使化風(fēng)險
事件監(jiān)聽器允許"this"轉(zhuǎn)義
失效的監(jiān)聽
public void processFile(String filename) throws IOException {
cancelButton.registerListener(this);
// open file, read it, process it
// might throw IOException
cancelButton.unregisterListener(this);
}
當(dāng)讀入文件時,產(chǎn)生異常,會造成取消注冊事件不能被執(zhí)行,取消登記的操作應(yīng)當(dāng)在 finally 塊中進(jìn)行,這樣,processFile() 方法的所有出口都會執(zhí)行它。