实现机制
- Collections工具类线程安全集合包装方法:通过在集合的方法中添加
synchronized
关键字,对方法进行同步控制,每次只能有一个线程访问集合的方法。例如Collections.synchronizedList(new ArrayList<>())
,在对该列表进行操作(如add
、remove
等)时,会同步执行。
- java.util.concurrent包下的线程安全集合:
- CopyOnWriteArrayList:写操作时,会复制一份原数组,在新数组上进行修改,最后将原数组引用指向新数组。读操作直接读取原数组,不需要加锁,这使得读操作性能较高。
- ConcurrentHashMap:在JDK1.7中采用分段锁机制,将哈希表分为多个段(Segment),每个段有自己的锁,不同段的写操作可以并发执行;JDK1.8中采用CAS + synchronized来实现,减少锁的粒度,提高并发性能。
适用场景
- Collections工具类线程安全集合包装方法:适用于读多写少,并且对性能要求不是特别高的场景。例如在一些简单的多线程数据统计场景中,操作频率不高,对性能要求相对较低。
- java.util.concurrent包下的线程安全集合:
- CopyOnWriteArrayList:非常适合读操作远多于写操作的场景,如事件监听列表。因为读操作无锁,性能好,但写操作因数组复制开销大。
- ConcurrentHashMap:适用于高并发读写的场景,如在高并发的Web应用中存储用户会话信息等,能提供较好的并发性能。
内存开销
- Collections工具类线程安全集合包装方法:内存开销相对较小,因为只是在原集合基础上添加同步控制,没有额外复杂的数据结构。
- java.util.concurrent包下的线程安全集合:
- CopyOnWriteArrayList:写操作时会复制数组,内存开销较大,特别是当集合元素较多时。
- ConcurrentHashMap:为了实现并发控制,会有一些额外的数据结构开销,如JDK1.7中的Segment数组等,但相比
CopyOnWriteArrayList
在写时的数组复制开销,在整体内存使用上会根据具体使用情况有所不同。
线程安全性
- Collections工具类线程安全集合包装方法:线程安全,通过
synchronized
保证了同一时间只有一个线程能访问集合方法,但在迭代集合时(如使用Iterator
),若不手动同步,仍然可能出现ConcurrentModificationException
,需要在迭代时手动同步集合。例如:
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
synchronizedList.add("a");
synchronizedList.add("b");
synchronized (synchronizedList) {
Iterator<String> iterator = synchronizedList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
- java.util.concurrent包下的线程安全集合:
- CopyOnWriteArrayList:线程安全,读操作无锁,写操作通过复制数组保证数据一致性,迭代器不会抛出
ConcurrentModificationException
,因为迭代的是旧数组。
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("a");
list.add("b");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
- **ConcurrentHashMap**:线程安全,在高并发环境下能保证数据的一致性和线程安全,通过锁分段或CAS + synchronized机制实现。
不同业务场景下的选择
- 读多写少且性能要求一般:选择
Collections.synchronizedList
等包装方法,如在一些简单的日志记录场景,记录操作频率不高,对性能要求不是特别苛刻。
- 读操作远多于写操作:选择
CopyOnWriteArrayList
,例如在事件监听器列表中,注册和注销监听器(写操作)频率低,而事件触发时遍历监听器列表(读操作)频率高。
- 高并发读写场景:选择
ConcurrentHashMap
,比如在高并发的电商系统中统计商品浏览量等场景,需要频繁进行读写操作。