The java.util.Collections
class provides the following static methods to wrap a collection into a thread-safe collection:
Collection<T> synchronizedCollection(Collection<T> c)
List<T> synchronizedList(List<T> list)
Map<K,V> synchronizedMap(Map<K,V> m)
Set<S> synchronizedSet(Set<T> s)
SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
The returned collection should be used instead of the wrapped collection.
When these thread-safe collection wrappers are used, the lock is obtained on them and not on the wrapped collection. Synchronization is not needed only when we perform simple operations like add, remove etc. While executing multiple operations such as put-if-absent or replace-if-found as an atomic operation you will have to use sychronization.
These synchronized collection wrappers provide fail-fast iterators. The iterators on these collections are not synchronized and should use synchronization explicitly to avoid ConcurrentModificationException
. However, the iterators on keys and values in case of Collections.synchronizedMap
i.e. iterators on keySet()
and values()
methods lock the thread-safe map and are not fail-fast.
These thread-safe collections allow storing null. They provide an up-to-date view of the wrapped collection. Their use is preferred over their alternative classes when there are more frequent modifications to the collection than traversal.
The Concurrency API in Java 5 provides ConcurrentHashMap
which is a synchronized map. It uses lock striping instead of locking the entire collection and hence provides better scalability in comparison with Collections.synchronizedMap
. The use of ConcurrentHashMap
should be preferred over Collections.synchronizedMap
when the read operations are more frequent than write operations on the map. ConcurrentHashMap
provides better scalabity than Hashtable.
Hashtable
is a thread-safe map but it does not allow storing null key unlike Collections.synchronizedMap
.
The Concurrency API also provides CopyOnWriteArrayList
which is a thread-safe copy of the wrapped List. Once the iterator on this list is created, any modifications to the wrapped list won’t be reflected in it. Similarly, this list never throws ConcurrentModificationException
since a new copy of the wrapped list gets created when its iterator is created. This iterator does not support any operations such as remove, add and set on it. The UnsupportedOperationException
is thrown when these methods are called it. The use of this class should be preferred over Collections.synchronizedList
when you want to use snapshot-style iterator.
The Oracle’s Java tutorial says that Vector
is slightly faster than Collections.synchronizedList.
The Concurrency API provides CopyOnWriteArraySet
which creates a thread-safe snapshot of the wrapped Set. It can be preferred over Collections.synchronizedSet
for better scalability when you don’t want to perform mutative operations.
Java 6 has introduced ConcurrentSkipListMap
and ConcurrentSkipListSet
which provide a thread-safe implementation of SortedMap
and SortedSet
respectively. The iterators of these collections do not throw ConcurrentModificationException
. Collections ordered in ascending order and their iterators are faster than the descending ones. These classes do not support insertion of null.