简介

本文是主要介绍,并发容器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容器相关类简介的更多相关文章

  1. Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理

    Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...

  2. Java 并发包中的高级同步工具

    Java 并发包中的高级同步工具 Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提供了各种功能支持,比如: 提供了线 ...

  3. Java 并发包中的读写锁及其实现分析

    1. 前言 在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时 刻可以允许多个读线程访问,但是在写线程访问时,所有 ...

  4. Java并发包中常用类小结(一)

    从JDK1.5以后,Java为我们引入了一个并发包,用于解决实际开发中经常用到的并发问题,那我们今天就来简单看一下相关的一些常见类的使用情况. 1.ConcurrentHashMap Concurre ...

  5. Java并发包中Semaphore的工作原理、源码分析及使用示例

    1. 信号量Semaphore的介绍 我们以一个停车场运作为例来说明信号量的作用.假设停车场只有三个车位,一开始三个车位都是空的.这时如果同时来了三辆车,看门人允许其中它们进入进入,然后放下车拦.以后 ...

  6. 【Android 应用开发】Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  7. Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  8. 优酷电视剧爬虫代码实现一:下载解析视频网站页面(4)补充: Java正则表达式Matcher.group(int group)相关类解析

    在Java正则表达式的相关类Matcher中,有如下几个方法: - int groupCount() - String group(int group) - int start(int group)  ...

  9. Java并发包中Lock的实现原理

    1. Lock 的简介及使用 Lock是java 1.5中引入的线程同步工具,它主要用于多线程下共享资源的控制.本质上Lock仅仅是一个接口(位于源码包中的java\util\concurrent\l ...

随机推荐

  1. windows环境下,anoconnda安装tensorflow

    最近对深度学习研究比较多,目前最火的Python深度学习库应该是tensorflow了. 为了方便,本人在windows下用anaconda来使用python,且同时安装了,anaconda2,3,3 ...

  2. 【php】php 连接数据库

    $mysql_server_name=""; //数据库服务器名称 $mysql_username=""; // 连接数据库用户名 $mysql_passwor ...

  3. Redis各种数据结构性能数据对比和性能优化实践

    很对不起大家,又是一篇乱序的文章,但是满满的干货,来源于实践,相信大家会有所收获.里面穿插一些感悟和生活故事,可以忽略不看.不过听大家普遍的反馈说这是其中最喜欢看的部分,好吧,就当学习之后轻松一下. ...

  4. Hibernate--inverse属性与cascade属性

    转载:http://www.cnblogs.com/otomedaybreak/archive/2012/01/17/2324772.html Hibernate 集合映射中,经常会使用到" ...

  5. HDU 6035---Colorful Tree(树形DP)

    题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...

  6. IT人不要一直做技术

    我现在是自己做,但我此前有多年在从事软件开发工作,当回过头来想一想自己,觉得特别想对那些初学JAVA/DOT.NET技术的朋友说点心里话,希望你们能从我们的体会中,多少受点启发(也许我说的不好,你不赞 ...

  7. Android 性能测试——Memory Monitor 工具

    Android 性能测试--Memory Monitor 工具 Memory Monitor能做什么? 实时查看App的内存分配情况 快速判断App是否由于GC操作造成卡顿 快速判断App的Crash ...

  8. css中的几个小tip(一)

    原博:http://www.webhek.com/post/7-tips-web-front-developer-must-know__trashed.html 1.元素的margin-top.mar ...

  9. Hibernate批量操作(一)

    在项目的开发过程之中,我们常会遇到数据的批量处理问题.在持久层采用Hibernate框架时,在进行批量操作时,需要考虑Hibernate实现机制带来的一些问题. 我们知道在每个Hibernate Se ...

  10. CentOS上javaweb开发环境搭建

    CentOS上javaweb开发环境搭建 安装jdk yum list java* yum install java-1.7.0-openjdk* -y java -version 安装tomcat ...