JUC并发容器--CopyOnWriteArrayList

JUC并发容器--CopyOnWriteArrayList

  • 原理
    • 缺陷
  • 常用API
  • 应用场景
  • CopyOnWriteArraySet

CopyOnWriteArrayList 是 Java 中的一种线程安全的 List,它是一个可变的数组,支持并发读和写。与普通的 ArrayList 不同,它的读取操作不需要加锁,因此具有很高的并发性能。

原理

CopyOnWriteArrayList 内部使用了一种称为“写时复制”的机制。当需要进行写操作时,它会创建一个新的数组,并将原始数组的内容复制到新数组中,然后进行写操作。因此,读操作不会被写操作阻塞,读操作返回的结果可能不是最新的,但是对于许多应用场景来说,这是可以接受的。此外,由于读操作不需要加锁,因此它可以支持更高的并发度。

JUC并发容器--CopyOnWriteArrayList_第1张图片

缺陷

CopyOnWriteArrayList 有几个缺点:

  • 消耗内存
    • 在写操作的时候,需要拷贝数组,会消耗内存,如果原数组的内容比较多的情况下,可能导致 young gc 或者 full gc。
  • 非实时读
    • 由于拷贝数组、新增元素都需要时间,所以调用一个set或add操作后,立马读取到数据可能是旧的,虽然 CopyOnWriteArrayList 能做到最终一致性,但是还是没法满足实时性要求;
  • 写时性能差
    • 当数据量比较大的时候,每次 add/set 都要重新复制数组,代价高昂,容易造成性能瓶颈。

常用API

CopyOnWriteArrayList phaser = new CopyOnWriteArrayList();
// 新增
copyOnWriteArrayList.add(1);
// 设置(指定下标)
copyOnWriteArrayList.set(0, 2);
// 获取(查询)
copyOnWriteArrayList.get(0);
// 删除(指定下标)
copyOnWriteArrayList.remove(0);
// 清空
copyOnWriteArrayList.clear();
// 是否为空
copyOnWriteArrayList.isEmpty();
// 是否包含
copyOnWriteArrayList.contains(1);
// 获取元素个数
copyOnWriteArrayList.size();
// 比较并添加元素(添加的元素如果存在则不会加到集合中)
copyOnWriteArrayList.addIfAbsent(1);

应用场景

  1. 读多写少的场景
    由于 CopyOnWriteArrayList 的读操作不需要加锁,因此它非常适合在读多写少的场景中使用。例如,一个读取频率比写入频率高得多的缓存,使用 CopyOnWriteArrayList 可以提高读取性能,并减少锁竞争的开销。

  2. 不需要实时更新的数据
    由于 CopyOnWriteArrayList 读取的数据可能不是最新的,因此它适合于不需要实时更新的数据。例如,在日志应用中,为了保证应用的性能,日志记录的操作可能被缓冲,并不是实时写入文件系统,而是在某个时刻批量写入。这种情况下,使用 CopyOnWriteArrayList 可以避免多个线程之间的竞争,提高应用的性能。

CopyOnWriteArraySet

基于CopyOnWriteArrayList实现,其唯一的不同是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法,其遍历当前Object数组,如Object数组中已有了当前元素,则直接返回,如果没有则放入Object数组的尾部,并返回。

你可能感兴趣的:(#,JUC,java)