Java 5中引入了并发包(java.util.concurrent),大大简化了多线程并发程序的开发。接下来我们分析一下引入concurrent包为多线程并发程序带来的变化。为清晰期间,进行对比说明。
第二,集合(Collections)的线程安全
1,Synchronized Collections
Vector和Hashtable是采用Synchronized的方案的线程安全的集合类。对应的线程不安全的类型为:ArrayList和HashMap。
另外,Java 1.2 引入了对集合线程安全便利封装的函数:Collections.synchronizedXxx (比如Collections.synchronizedList)。
示例如下:
| List<String> mySafeList = Collections.synchronizedList(new ArrayList<String>()); |
| Map<String, Object> mySafeMap = Collections.synchronizedMap(new HashMap<String, Object>()); |
这样被封装过的集合在被访问的各个方法均为等价于加了Synchronized修饰符的。
2,Concurrent Collections
Synchronized Collections性能比较低,而ArrayList和HashMap这类又在多线程访问的时候不安全,Java 5引入了基于copywirte、Lock Striping和compare and set等技术的Concurrent Collections。
| 类型 | 非线程安全版 | 采用技术 | 备注 |
| ConcurrentHashMap | HashMap | Lock Striping & compare and set | 将key分组,每组使用不同的同步锁 |
| ConcurrentSkipListMap(Java 6) | SortedMap | 如上 | 如上 |
| CopyOnWriteArrayList | ArrayList | copy on wirte | 发生修改时候做copy,新老版本分离,保证读的高性能,适用于以读为主的情况 |
| ConcurrentSkipListSet(Java 6) | SortedSet | 如上 | 如上 |
下面代码简单示例了采用Lock Striping技术实现一个线程安全的高效的Map。
| @ThreadSafe private static class Node { ... } public StripedMap(int numBuckets) { private final int hash(Object key) { public Object get(Object key) { public void clear() { |
下面是各类Map在cpu个数增加情况下的性能增长对比图:

可以看到Synchronized Collections在cpu个数增加到2个时,性能严重下滑,以后没有什么变化。而新的Concurrent Collections保持接近lg(n)的增长。
第三,原子变量(Atomic Variable)
解决“cpu cache导致的线程安全问题”的另外一个简单的方式就是使用Java 5提供的原子变量:AtomicInteger, AtomicLong, AtomicBoolean, 和 AtomicReference。
浮点数可以使用 Float.floatToIntBits或者 Double.doubleToLongBits的方法进行转换。和volatile相比还提供了compareAndSet的方法,以便支持基于此的实现复杂高效的并发处理。
未完待续...




