Java中CopyOnWriteArrayList使用方法

CopyOnWriteArrayList非常适合读多写少的场景。

真实故事:2 02 0年Java并发编程大会案例。
时间:读操作需要1 ms,写操作需要1 00ms(列表大小1 000)。
Numbers:内存开销比ArrayList高3 -5 倍。

这里有一个陷阱:频繁写入时性能不佳。
不要相信:差的一致性可以满足任何业务。

监控写入操作的频率和内存使用情况。

为什么线程安全的List推荐使用CopyOnWriteArrayList,而不是Vector

你好,你问了一个好问题。
我对此很熟悉。
这样的废话不说,先说一下我当年遇到的坑。

我记得有一年我带领一个小团队构建一个电子商务后端系统。
那时Java还处于1 .6 版本。
有必要建立全球黑名单,防止欺诈订单。
一开始我以为很简单,但是我做一个Vector不就可以了吗?毕竟当时的书上说,对于线程安全的列表,应该选择向量或者哈希表。

结果如何?我一上线,所有的请求都停止了。
后来发现后台黑名单列表更新非常频繁,查询黑名单的人也越来越多。
想一想。
Vector 的锁对于读和写都是锁定的。
如果一个线程正在写入,则另一个线程无法读取。
不会被卡住吗?
再看一下 CopyOnWriteArrayList。
我也是后来才知道这个事情的。
想一想。
想象一下,如果不需要任何读操作锁定,直接访问数组数据会快得多。
仅在写入操作之后才保持锁定,并且在修改后复制新数组。
后来我将黑名单模块更改为使用CopyOnWriteArrayList,性能立即得到改善。
后台日志一目了然,老板还表扬了我。

所以不要使用Vector。
CopyOnWriteArrayList 是正确的方法。
尤其是现在java8 和java1 1 的新版本,并发控制更好了,使用CopyOnWriteArrayList也更好玩了。

我们以扩展为例来谈谈。
缩放 Vector 时,默认情况下将其容量加倍。
上次扩张是1 000,这次是2 000。
中间1 000个是空的,浪费内存。
CopyOnWriteArrayList 怎么样?每添加一个元素,就会创建一个新数组,并且其长度增加1 它的精确度如何?在我上次的测试中,我使用 CopyOnWriteArrayList 作为缓存,内存利用率提高了 1 -2 个百分点。
虽然看起来没什么大不了的,但确实省钱了。

此外,CopyOnWriteArrayList 的写时复制机制可以防止锁争用。
考虑到在高并发场景下,写入会更少,读取会更多。
CopyOnWriteArrayList 允许读取操作完全并行化。
那么向量呢?所有任务都必须排队。
效率能一样吗?
当然,CopyOnWriteArrayList并不完美。
例如,如果您需要数据的实时一致性,您可能无法处理它,并且您仍然会在读取操作中获得过时的数据。
但是,如果您正在执行需要更多读取和更少写入的缓存和事件侦听器列表,那么这绝对是您的首选。

总之,对于线程安全列表,CopyOnWriteArrayList现在是首选,不要再碰Vector了。
当时,使用矢量几乎毁掉了这个项目。
您应该将此视为警告。