在JDK1.2之前同步容器類包括Vector、Hashtable,這兩個容器通過內置鎖synchronized保證了同步。后面的ArrayList、LinkedList、HashMap、LinkedHashMap等等都不是線程安全的,沒有添加同步機制。但是JDK后面的Collections類也提供了這些常見容器類的同步容器類實現:將它們的狀態封裝起來,並對每個公共方法都進行同步,使得每次只有一個線程能訪問容器狀態。
在Collections這個類下面提供了一些靜態類和靜態方法。比如常見的同步容器類的創建方法:
1 public static <T> List<T> synchronizedList(List<T> list); 2 3 public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m); 4 5 public static <T> Set<T> synchronizedSet(Set<T> s); 6 7 public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m); 8 9 .....
通過這些靜態方法將一個傳遞進去的集合包裝成同步的集合。這里很明顯就用到了設計模式中的裝飾器模式。
Collections同步容器類迭代的線程安全:
如果同步容器類的數據量很大,迭代的時候占用時間較長。迭代過程中可能會出現別的線程修改了容器的數據,這樣迭代的時候可能會拋出異常(比如迭代到索引最后的元素,這時候另外一個線程刪除了這個元素,這時候會拋出數組越界的異常)。
但是如果迭代過程中加鎖,那么就會出現性能問題。其中一種解決方案就是克隆容器,再迭代克隆的容器。(克隆期間需要加鎖),但是克隆也是耗費CPU性能的。所以沒有十全十美的辦法。