口袋勇气免DVD硬盘版
4.9G · 2025-09-18
原文来自于:zha-ge.cn/java/77
有那么一天,咖啡喝多了,脑袋嗡嗡响,领导突然“温柔”地甩过来一坨需求:“你这List用的安全吗?多线程下会不会爆炸?”
我一口激浪差点喷屏幕,线程安全集合,这不是老生常谈嘛。可是等我翻代码,才发现自己其实只认识 Collections.synchronizedList
和 Vector
,其他的都进垃圾回收站了。哎,这锅不能背,得扒一扒 Java 里的线程安全集合到底有几路豪杰。
Java 集合家族其实超级大,线程安全的那些,堪比武林门派,各有绝技。
Vector
, Hashtable
这些上古遗迹,虽然老,但能保命。Collections.synchronizedXXX
工厂方法,给老集合套个线程安全“特效皮肤”。ConcurrentHashMap
, CopyOnWriteArrayList
等并发大佬,JDK5后出道,秒杀前辈。我还腾了个小表格,请叫我表哥:
集合名 | 线程安全性 | 优势 | 劣势 |
---|---|---|---|
Vector | 安全 | 祖传防爆,简单易懂 | 性能糟糕 |
Collections.synchronizedList | 安全 | 易于转换,老代码福音 | 性能一般,颗粒粗 |
ConcurrentHashMap | 超级安全 | 读多写少场景无敌,细粒度锁 | 写多可能瓶颈 |
CopyOnWriteArrayList | 读安全 | 读写分离,读场景快 | 写操作开销大 |
我一开始跑路 Collections.synchronizedList
,写了个多线程测试自信满满,结果直接春哥再临。问题出在哪?
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
syncList.add(Thread.currentThread().getName());
}).start();
}
// 等等再遍历
for (String name : syncList) {
System.out.println(name);
}
别问我为啥会ConcurrentModificationException,问就是for-each遍历没加锁。线程安全这个事儿,还得自己上心啊!上了锁,世界才安静:
synchronized (syncList) {
for (String name : syncList) {
System.out.println(name);
}
}
但这不优雅啊朋友,终于理解为啥 CopyOnWriteArrayList 会受宠。
最后,我现在面对线程安全集合都学会了一个骚操作:先问,啥场景?多读还是多写?要啥功能? 真不确定,用 Concurrent 系列,起码不会坑队友。 写代码就是这样嘛,边挨锤边成长,踩坑万岁!