文档章节

CopyOnWriteArraylist解析

令飞
 令飞
发布于 2015/04/18 22:53
字数 851
阅读 139
收藏 0
点赞 0
评论 0

    自从JDK1.5引入引入concurrentHashmap,CopyOnWriteArraylist等并发集合后,java集合体系得到了很大的完善,我们有多了不少特殊情境的选择。     

    我们都知道,ArrayList存数数据的结构为数组,获取数据是根据数组下标,因此获取数据速度很快,而插入(中间)数据,删除数据却需要copy数组,因此速度较慢,而相比之下, CopyOnWriteArraylist底层的存储依然是数组,但是基本操作却不大一样。


好处(使用场景):

 Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器非常有用,可以在非常多的并发场景中使用到。

CopyOnWriteArrayList通过修改时拷贝原数组,而获取数组时返回老数组(相当于快照),使得修改和查看(遍历)的线程操作的是不同数组,达到避免并发修改的问题

 

缺点(不宜使用):

     1.内存占用问题

     因为CopyOnWrite的写时复制机制,所以在进行写操作的时候,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象(注意:在复制的时候只是复制容器里的引用,只是在写的时候会创建新对象添加到新容器里,而旧容器的对象还在使用,所以有两份对象内存)。如果这些对象占用的内存比较大,比如说200M左右,那么再写入100M数据进去,内存就会占用300M,那么这个时候很有可能造成频繁的Yong GC和Full GC。之前我们系统中使用了一个服务由于每晚使用CopyOnWrite机制更新大对象,造成了每晚15秒的Full GC,应用响应时间也随之变长。

  针对内存占用问题,可以通过压缩容器中的元素的方法来减少大对象的内存消耗,比如,如果元素全是10进制的数字,可以考虑把它压缩成36进制或64进制。或者不使用CopyOnWrite容器,而使用其他的并发容器,如ConcurrentHashMap

 2.数据一致性问题

CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。

        3.性能。

    每次写都要复制的操作自然造成操作性能的下降。

代码:

 添加

 

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#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();
        }
    }

 

通过Arrays的copyOf方式复制数组,同时,写的操作是需要并发控制的,采用了显示锁

写的操作直接对新的数组执行


 

获取数组

  final Object[] getArray() {
        return array;
    }

 


 

© 著作权归作者所有

共有 人打赏支持
令飞
粉丝 45
博文 21
码字总数 14127
作品 0
杭州
程序员
并发编程6:CopyOnWriteArrayList 的写时复制

首先提个问题: 线程安全的 List 集合有什么? CopyOnWriteArrayList 的特点以及使用场景? 如果这个问题你答不上来,那这篇文章可能就对你有些价值。 读完本文你将了解: CopyOnWriteArray...

u011240877 ⋅ 2017/08/20 ⋅ 0

ArrayList源码解析之fail-fast机制深入理解

概要 前面,我们已经学习了ArrayList。接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解。 1 fail-fast简介 fail-fast 机制是java集合(Collection)中的一种错误机制。 当多个...

sihailoveyan ⋅ 05/09 ⋅ 0

【追光者系列】HikariCP源码分析之ConcurrentBag

摘自【工匠小猪猪的技术世界】 1.这是一个系列,有兴趣的朋友可以持续关注 2.如果你有HikariCP使用上的问题,可以给我留言,我们一起沟通讨论 3.希望大家可以提供我一些案例,我也希望可以支...

查查 ⋅ 05/02 ⋅ 0

CopyOnWriteArrayList与Collections.synchronizedMap性能

平台: AMD X2 5400+,2G RAM,JDK6,eclipse 3.4 CopyOnWriteArrayList:专为多线程并发设计的容器,“写入时复制”策略。 Collections.synchronizedMap:同步容器,独占策略。 分析: 可以...

MarkCo ⋅ 2016/04/20 ⋅ 0

线程安全的CopyOnWriteArrayList介绍

证明CopyOnWriteArrayList是线程安全的 先写一段代码证明CopyOnWriteArrayList确实是线程安全的。 ReadThread.java WriteThread.java 测试程序:TestCopyOnWriteArrayList.java 运行上面的代...

qq948939246 ⋅ 03/22 ⋅ 0

CopyOnWriteArrayList理解

CopyOnWriteArrayList,因何而存在? ArrayList的一个线程安全的变体,其所有可变操作(add、set等)都是通过对底层数组进行一次新的复制来实现的,代价昂贵。 CopyOnWriteArrayList,是因”...

Mr&Cheng ⋅ 2013/01/20 ⋅ 0

CopyOnWriteArrayList详解

CopyOnWriteArrayList是ArrayList 的一个线程安全的变体,其中所有可变操作(add、set等等)都是通过对底层数组进行一次新的复制来实现的。 这一般需要很大的开销,但是当遍历操作的数量大大...

古月楼 ⋅ 2013/10/08 ⋅ 7

并发容器:CopyOnWriteArrayList

0.ConpyOnWriteArrayList的使用场景 在多线程中,如果A线程在读取一个List时,B线程在向里面add数据,会抛出异常:java.util.ConcurrentModificationException 运行这段代码,会抛出java.ut...

似是而非Sage ⋅ 2016/08/16 ⋅ 0

CopyOnWriteArrayList的排序方法

在多线程中,使用ArrayList 进行remove操作时,会报异常。改用CopyOnWriteArrayList,若再进Collections.sort(copyOnWriteArrayList, myComparator)时,会报异常: java.lang.UnsupportedOpe...

liuhuics10 ⋅ 2016/03/25 ⋅ 0

CopyOnWriteArrayList

除了加锁外,其实还有一种方式可以防止并发修改异常,这就是将读写分离技术(不是数据库上的)。 先回顾一下一个常识: 1、JAVA中“=”操作只是将引用和某个对象关联,假如同时有一个线程将引...

Mr&Cheng ⋅ 2013/01/20 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

收集自网络的wordpress 分页导航的代码教程(全网最全版)

wordpress 分页导航是用来切换文章的一个功能,添加了 wordpress 分页导航后,用户即可自由到达指定的页面数浏览分类文章,而这样的一个很简单功能却有很多朋友在用插件:WP-PageNavi,插件的...

Rhymo-Wu ⋅ 29分钟前 ⋅ 0

微服务 WildFly Swarm 入门

Hello World 就像前面章节中的其他框架一样,我们希望添加一些基本的 Hello-world 功能,然后在其上逐步添加更多的功能。让我们从在我们的项目中创建一个 HolaResources 开始。您可以使用您的...

woshixin ⋅ 36分钟前 ⋅ 0

Maven的安装和Eclipse的配置

1. 下载Maven 下载地址 2. 解压压缩包,放到自己习惯的硬盘中 此处我将其放到了 D:\Tools 目录下。 3. 配置环境变量 右键此电脑 -> 属性 -> 高级系统设置 -> 环境变量。 在系统变量中新建,变...

影狼 ⋅ 43分钟前 ⋅ 0

python pip使用国内镜像的方法

国内源 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 华中理工大学:http://......

良言 ⋅ 44分钟前 ⋅ 0

对于url变化的spa应该如何使用微信jssdk

使用vue单页面碰上微信jssdk config验证失败的坑。第一次成功 之后切换页面全部失败,找到了解决方法,第一次验证成功后保存验证信息 切换页面时验证信息直接拿来用,加一个wx.error() 失败时...

孙冠峰 ⋅ 48分钟前 ⋅ 0

Spring Cloud Gateway 一般集成

SCF发布,带来很多新东西,不过少了点教程,打开方式又和以前的不一样,比如这个SCG,压根就没有入门指导,所以这里写一个,以备后用。 一、集成 pom.xml <dependency> <groupI...

kut ⋅ 52分钟前 ⋅ 0

建造模式

《JAVA与模式》之建造模式

Cobbage ⋅ 今天 ⋅ 0

WePY框架开发的小程序如何在微信web开发者工具中运行起来

一、首先需要安装node.js,安装步骤如下: 首先下载安装包 https://nodejs.org/en/download/ 点击下载相应的zip版本 然后将文件夹解压到任意目录 比如我这里解压到了:C:\Program Files\node...

Helios51 ⋅ 今天 ⋅ 0

使用EnumSet 代替位域(32)

1、位域(Bit field):使用or 运算将几个常量合并到一个集合中 位操作,可以有效地执行 AND 、OR 这样的位操作 但是 位域比int 常量枚举缺点更多 2、java.util 包里面的EnumSet 类是有效的替...

职业搬砖20年 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部