JAVA高并发学习 - 使用Collections工具类将非线程安全类转为线程安全
HashMap,ArrayList,LinkedList,Set等集合都不是线程安全的集合。使用Collections工具类提供的方法,可以将其变为线程安全的集合。
使用方式如下:
public static Map map = Collections.synchronizedMap(new HashMap())
Collections.synchronizedMap()方法会生成一个Collections.SynchronizedMap的Map。
它使用委托将自己所有Map的相关功能交给传入的HashMap实现,而自己则主要负责保证线程的安全。
private static class SynchronizedMap<K,V>
implements Map<K,V>, Serializable {
private static final long serialVersionUID = 1978198479659022715L;
private final Map<K,V> m; // Backing Map
final Object mutex; // Object on which to synchronize
SynchronizedMap(Map<K,V> m) {
this.m = Objects.requireNonNull(m);
mutex = this;
}
SynchronizedMap(Map<K,V> m, Object mutex) {
this.m = m;
this.mutex = mutex;
}
//...
}
通过mutex实现对这个m的互斥操作,从而实现线程安全。比如,对于Map的一些常见方法,它的实现如下:
//...
public int size() {
synchronized (mutex) {return m.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return m.isEmpty();}
}
public boolean containsKey(Object key) {
synchronized (mutex) {return m.containsKey(key);}
}
public boolean containsValue(Object value) {
synchronized (mutex) {return m.containsValue(value);}
}
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}
public V put(K key, V value) {
synchronized (mutex) {return m.put(key, value);}
}
public V remove(Object key) {
synchronized (mutex) {return m.remove(key);}
}
public void putAll(Map<? extends K, ? extends V> map) {
synchronized (mutex) {m.putAll(map);}
}
public void clear() {
synchronized (mutex) {m.clear();}
}
//...
虽然这个包装的Map可以满足线程安全的要求,但是它在多线程环境中的性能表现不算太好。
无论是对Map的读取和写入,都需要获得mutex的锁,这会导致所有对Map的操作全部进入等待状态,直到mutex锁可用。
如果并发级别不高,那么一般也够用,但是,高并发环境中,需要寻求新的解决方案。
接下来学习更加专业的并发集合。