首页 > 编程语言 >JAVA并发容器-写时复制容器

JAVA并发容器-写时复制容器

时间:2022-11-04 14:09:34浏览次数:65  
标签:容器 JAVA CopyOnWriteArraySet copyOnWriteArrayList add copyOnWriteArraySet CopyOnW


写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。

这样做的好处是我们可以对容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以写时复制容器也是一种读写分离的思想,读和写不同的容器。如果读的时候有多个线程正在向容器添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的,只能保证最终一致性

适用读多写少的并发场景,常见应用:白名单/黑名单, 商品类目的访问和更新场景。

CopyOnWriteArrayList和CopyOnWriteArraySet就是写时复制容器。

CopyOnWriteArrayList 类图

JAVA并发容器-写时复制容器_CopyOnWriteArraySet


底层依然是数组,基于ReentrantLock来做并发控制。

add()

public boolean add(E e) {
final ReentrantLock lock = this.lock;
// 加锁
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
// 复制原数组
Object[] newElements = Arrays.copyOf(elements, len + 1);
// 添加元素
newElements[len] = e;
// 替换数组
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}

CopyOnWriteArraySet类图

JAVA并发容器-写时复制容器_CopyOnWriteArrayList_02


CopyOnWriteArraySet就是基于CopyOnWriteArrayList来实现的。

测试方法

@Test
public void testCopyOnWrite() {
CopyOnWriteArrayList<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
copyOnWriteArrayList.add(5);
copyOnWriteArrayList.add(3);
copyOnWriteArrayList.add(4);
copyOnWriteArrayList.add(2);
copyOnWriteArrayList.add(3);

System.out.println(copyOnWriteArrayList);

CopyOnWriteArraySet<Integer> copyOnWriteArraySet = new CopyOnWriteArraySet<>();
copyOnWriteArraySet.add(5);
copyOnWriteArraySet.add(3);
copyOnWriteArraySet.add(4);
copyOnWriteArraySet.add(2);
copyOnWriteArraySet.add(3);

System.out.println(copyOnWriteArraySet);
}

输出:

[5, 3, 4, 2, 3]
[5, 3, 4, 2]

源码

​https://github.com/wyh-spring-ecosystem-student/spring-boot-student/tree/releases​

spring-boot-student-concurrent 工程

layering-cache

为监控而生的多级缓存框架 layering-cache这是我开源的一个多级缓存框架的实现,如果有兴趣可以看一下


标签:容器,JAVA,CopyOnWriteArraySet,copyOnWriteArrayList,add,copyOnWriteArraySet,CopyOnW
From: https://blog.51cto.com/u_15861563/5823696

相关文章

  • Java中的指令重排
    在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。重排序分3种类型:编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。......
  • JAVA并发容器-ConcurrentHashMap 1.7和1.8 源码解析
    HashMap是一个线程不安全的类,在并发情况下会产生很多问题,详情可以参考​​HashMap源码解析​​;HashTable是线程安全的类,但是它使用的是synchronized来保证线程安全,线程竞争......
  • Java中的锁
    锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源(但是有些锁可以允许多个线程并发的访问共享资源,比如读写锁)。Lock和synchronized......
  • Elasticsearch 同时使用should和must 只有must生效,java代码解决方案
    ES中同时使用should和must导致只有must生效解决方案失效的原因就是must和should在一起使用会不生效,如果全部都是must是不影响的.加入一个字段需要有类似url=aor......
  • java 压缩图片
    FilesourceFile=newFile("F:\\1.png");FiletargetFile=newFile("F:\\2.png");Thumbnails.of(sourceFile).scale(0.3f).toFile(targetFile)......
  • JAVA CST时间 转换成Date
    格式化CST时间SimpleDateFormatsdf=newSimpleDateFormat("EEEMMMddHH:mm:sszzzyyyy",Locale.US);CST时间转换成字符串,实体中为date类型的toString()转换即......
  • Java线程状态详解
    Java的每个线程都具有自己的状态,Thread类中成员变量threadStatus存储了线程的状态: privatevolatileintthreadStatus=0; 在Thread类中也定义了状态的枚举,共六......
  • 【java技术总结】Java-9中List.of()和Arrays.asList()的区别及原因分析
    1.List.of()和Arrays.asList()的区别?List.of()不可以插入null,Arrays.asList()可以。List.of()生成的List不可以修改,Arrays.asList()可以。List.of()原数组修改不会影响......
  • 13. Java 面向对象编程
    Java面向对象编程Java的核心思想就是OOP1.初识面向对象面向过程&面向对象面向过程思想步骤清晰简单,第一步做什么,第二步做什么.....面对过程适合处理一些......
  • java如何实现原子操作CAS
    在Java中可以通过锁和循环CAS的方式来实现原子操作。使用循环CAS实现原子操作JVM中的CAS操作正是利用了处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行......