包裝器實現
包裝器實現是一種將它們的實際工作委托給一個特定 對象集 的實現,它在該 對象集 所提供的功能之上又增加了額外的功能。 對design patterns(設計樣式)
愛好者來說,這是一個 decorator(油漆工) 樣式。雖然有點異國情調,但確實簡單明了。
<!-- frame contents -->
<!-- /frame contents -->
這些實現是匿名的:不是提供一個公共類,JDK 提供一個 static factory method(靜態方法)。 所有這些都可以在僅包含靜態方法的Collections
API 中找到。
同步包裝器(Synchronization Wrappers)
同步包裝器將自動同步(線程安全的)添加到一個任意的 對象集。6個 核心 對象集 接口中的每一個都對應一個靜態方法:
public static Collection synchronizedCollection(Collection c);
public static Set synchronizedSet(Set s);
public static List synchronizedList(List list);
public static Map synchronizedMap(Map m);
public static SortedSet synchronizedSortedSet(SortedSet s);
public static SortedMap synchronizedSortedMap(SortedMap m);
每一個這樣的方法都返回一個由特定 對象集 作為後備的同步(線程安全的)Collection。 為保證串行存取,所有對後備 對象集 的存取都必須通過返回的
對象集 來完成,這一點是至關重要的。 保證這一點的一個簡便辦法是不要保持對後備 對象集 的引用, 創建這樣的同步 對象集 是一個小技巧:
List list = Collections.synchronizedList(new ArrayList());
一個用這種方式創建的對象集,每一比特都是線程安全的,就象VectorM那樣的"正常"同步 對象集 一樣。 在需要並發存取情況下,在返回的
對象集 上迭代時,用戶對返回的 對象集 做手工同步是十分必要的。 這是因為迭代是通過對對象集 的多重調用完成的,它必須被編寫為一個單獨的最小單元操作(atomic
operation)。在一個包裝器同步的 對象集 上的迭代慣用程序如下所示:
Collection c = Collections.synchronizedCollection(myCollection);
synchronized(c) {
Iterator i = c.iterator(); // Must be in the synchronized block!
while (i.hasNext())
foo(i.next());
}
在一個同步 Map 的 Collection視圖上的迭代慣用程序與上述程序相似,但有一個訣竅,那就是,當在同步 Map 的Collection視圖上迭代時,
用戶必須對同步 Map 做手工同步,而不是對 Collection視圖本身做同步:
<!-- frame contents -->
<!-- /frame contents -->
Map m = Collections.synchronizedMap(new HashMap());
...
Set s = m.keySet(); // Needn"t be in synchronized block
...
synchronized(m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
包裝器實現的一個小的缺陷是你不能執行一個包裝器實現的非接口操作。因此,比如在上面的 List 的例子中,你就不能調用包裝的ArrayList上的ensureCapacity