Java并发包中CopyOnWrite容器相关类简介
简介:
本文是主要介绍,并发容器CopyOnWriteArrayList和CopyOnWriteArraySet(不含重复元素的并发容器)的基本原理和使用示例。
欢迎探讨,如有错误敬请指正
如需转载,请注明出处 http://www.cnblogs.com/nullzx/
1. CopyOnWriteArrayList
从类的名字我们可以看出,该类是基于ArrayList类实现的。而CopyOnWrite的意思显然借鉴了操作系统中写时拷贝的思想。该容器主要有以下特点:
1)读取该容器中元素时,不加锁。
2)写操作,会加锁,也就是说多个线程进行写入操作时会逐个获取锁后进行写入。
3)写操作不会影响读操作,也就是说线程要进行读操作时,不会因为有线程正在进行写操作而阻塞。
下面是写操作源代码
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
E oldValue = get(elements, index); if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;
} finally {
lock.unlock();
}
}
工作原理:在CopyOnWriteArrayList类中,定一了一个数组private transient volatile Object[] array;容器中存储的对象的索引都会放在这个数组中。
写操作首先会获取锁。当获取锁成功后,复制该数组到一个新的数组newElements中,然后修改或者添加某个元素(注意这个时候如果有线程来读取该数组中的某个值,由于读操作不需要获取锁,所以不会被阻塞,但是可能不能读取到最新修改后的值)。修改后,让array指向经过修改后的新数组newElements,原array指向的数组会被垃圾回收器回收。
下面的代码是CopyOnWriteArrayList的演示例程
package javalearning; import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /*CopyOnWriteArrayList演示例程*/
public class CopyOnWriteArrayListDemo {
/*定义一个CopyOnWriteArrayList对象,读线程和写线程会同时使用它*/
private CopyOnWriteArrayList<Integer> cowal = new CopyOnWriteArrayList<Integer>();
{
/*对CopyOnWriteArrayList对象初始化*/
cowal.add(1);
cowal.add(2);
cowal.add(3);
} private Random rnd = new Random(); public class ReadThread implements Runnable{
private String id; public ReadThread(String id){
this.id = id;
} @Override
public void run() {
try {
Thread.sleep(rnd.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
/*读线程会打印出CopyOnWriteArrayList对象的所有数值*/
System.out.println(id + " " + cowal.toString());
} } public class WriteThread implements Runnable{ /*写线程会将CopyOnWriteArrayList对象的所有数值加1*/
@Override
public void run() {
for(int i = 0; i < cowal.size(); i++){
int x = cowal.get(i); /*每修改一个元素之前加锁*/
cowal.set(i, x+1);
/*修改完一个元素后释放锁*/ try{
Thread.sleep(rnd.nextInt(1000));
}catch(InterruptedException e){
e.printStackTrace();
}
}
} } public static void main(String[] args){
ExecutorService es = Executors.newCachedThreadPool();
CopyOnWriteArrayListDemo demo = new CopyOnWriteArrayListDemo();
/*创建两个读线程*/
es.execute(demo.new ReadThread("r1"));
es.execute(demo.new ReadThread("r2"));
/*创建两个写线程*/
es.execute(demo.new WriteThread());
es.execute(demo.new WriteThread()); es.shutdown();
while(!es.isTerminated()){
;
}
System.out.println("=====================");
/*CopyOnWriteArrayList对象中的最终值*/
System.out.println("eventual " + demo.cowal.toString());
}
}
全部结束后,最终结果和我们预想的一致。
r2 [2, 3, 3]
r1 [2, 4, 3]
=====================
eventual [2, 4, 5]
2. CopyOnWriteArraySet
CopyOnWriteArraySet是一个不存贮重复对象的写时拷贝容器。它的实现的原理很简单,在其内部定义了一个CopyOnWriteArrayList对象al,当向该容器添加一个对象时,会调用addIfAbsent方法。
public boolean add(E e) {
return al.addIfAbsent(e);
}
3. 参考内容
[1] 聊聊并发-Java中的Copy-On-Write容器 | 并发编程网 – ifeve.com
[2] Java并发编程:并发容器之CopyOnWriteArrayList(转载)
Java并发包中CopyOnWrite容器相关类简介的更多相关文章
- Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理
Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...
- Java 并发包中的高级同步工具
Java 并发包中的高级同步工具 Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提供了各种功能支持,比如: 提供了线 ...
- Java 并发包中的读写锁及其实现分析
1. 前言 在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时 刻可以允许多个读线程访问,但是在写线程访问时,所有 ...
- Java并发包中常用类小结(一)
从JDK1.5以后,Java为我们引入了一个并发包,用于解决实际开发中经常用到的并发问题,那我们今天就来简单看一下相关的一些常见类的使用情况. 1.ConcurrentHashMap Concurre ...
- Java并发包中Semaphore的工作原理、源码分析及使用示例
1. 信号量Semaphore的介绍 我们以一个停车场运作为例来说明信号量的作用.假设停车场只有三个车位,一开始三个车位都是空的.这时如果同时来了三辆车,看门人允许其中它们进入进入,然后放下车拦.以后 ...
- 【Android 应用开发】Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介
Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...
- Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介
Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...
- 优酷电视剧爬虫代码实现一:下载解析视频网站页面(4)补充: Java正则表达式Matcher.group(int group)相关类解析
在Java正则表达式的相关类Matcher中,有如下几个方法: - int groupCount() - String group(int group) - int start(int group) ...
- Java并发包中Lock的实现原理
1. Lock 的简介及使用 Lock是java 1.5中引入的线程同步工具,它主要用于多线程下共享资源的控制.本质上Lock仅仅是一个接口(位于源码包中的java\util\concurrent\l ...
随机推荐
- 在Docker Hub上查找可用的Image映像
任何人都可以创建Docker Image映像,你可以浏览Docker Hub来查找这些Image映像. 定位Whalesay 映像 打开你的浏览器,浏览Docker Hub: Docker Hub包含 ...
- Python开发【笔记】:单线程下执行多个定时任务
单线程多定时任务 前言:公司业务需求,实例当中大量需要启动定时器的操作:大家都知道python中的定时器用的是threading.Timer,每当启动一个定时器时,程序内部起了一个线程,定时器触发执行 ...
- 关于javacc的认识
http://www.cnblogs.com/Gavin_Liu/archive/2009/03/07/1405029.html
- 初识RabbitMQ系列之一:简单介绍
一:RabbitMQ是什么? 众所周知,MQ是Message Queue(消息队列)的意思,RabbitMQ就是众多MQ框架其中的一款,开源实现了AMQP协议(官网:http://www.amqp. ...
- centos下编译安装Openssl
yum install -y zlib*mkdir /datacd /data下载好tar包tar zxf openssl-1.0.2g.tar.gzcd openssl-1.0.2g./config ...
- Java微信开发_02_本地服务器映射外网
一.工具列表 内网穿透的相关工具有: (1)natapp 官网 :https://natapp.cn/ (2)花生壳 官网:https://console.oray.com/ (2)ngrok 官网: ...
- 度度熊与邪恶大魔王 DP | 完全背包
Problem Description 度度熊为了拯救可爱的公主,于是与邪恶大魔王战斗起来. 邪恶大魔王的麾下有n个怪兽,每个怪兽有a[i]的生命值,以及b[i]的防御力. 度度熊一共拥有m种攻击方式 ...
- LAP+mysql-主从+redis
Redis是一个开源的,内存中的数据结构存储系统,他可以用作数据库,缓存和消息中间介.支持多种类型数据库结构,如字符串(strings),散列(hashes),列表(lists),集合(sets),有 ...
- idea如何添加外部jar包
假设我们要将G:\ModuleAPI_Java_2.2.0.0 .jar导入工程中: 首先,在mvn命令行执行下面命令: mvn install:install-file -Dfile=G:\Modu ...
- Java设计模式学习笔记,二:工厂模式
工厂模式,主要实现了创建者和调用者的分离. 分类:1.简单工厂模式:2.工厂方法模式:3.抽象工厂模式. 核心:实例化对象时,用工厂方法代替new操作. 一.简单工厂模式 也叫静态工厂模式,工厂类中实 ...