Java并发编程原理与实战三十四:并发容器CopyOnWriteArrayList原理与使用
1、ArrayList的实现原理是怎样的呢?
顾名思义,当数组有变化时重新建立一个新的数组。其设计是对于线程安全容器Vector使用中出现问题的一种解.
在Vector容器中,当需要执行复合操作
代码1
class Observable
{
private List<Observer> observers=new Vector<Observer>(); public void addObserver(){...}
public void removeObserver(){...}
public void notify()
{
Iterator<Observer> itr=observers.iterator();
while(itr.hasNext()){
Observer observer=itr.next();
observer.notify();
}
return;
}
}
Observable中的notify方法在单线程中的实现是正常的,但在多线程中,由于在notify执行过程中observers数组的内容可能会发生改变,导致遍历失效.即使observers本身是线程安全的也于是无补
通常解决这个问题,可以使用同步方法或者加锁
代码2
class Observable
{
private List<Observer> observers=new Vector<Observer>(); public synchronized void addObserver(){...} public synchronized void removeObserver(){...} //同步方法
public synchronized void notify()
{
Iterator<Observer> itr=observers.iterator();
while(itr.hasNext()){
Observer observer=itr.next();
observer.notify();
}
return;
}
}
这样的解决方案中notify的同步导致另外一个问题,即活跃性问题.当observers中有很多元素或者每一个元素的notify方法调用需要很久时,此方法将长时间持有锁.导致其他任何想修改observers的行为阻塞.最后严重影响程序性能
CopyOnWriteArrayList即在这种场景下使用.一个需要在多线程中操作,并且频繁遍历.
其解决了由于长时间锁定整个数组导致的性能问题.
其解决方案即写时拷贝。
我们先来贴出使用CopyOnWriteArrayList的Observable代码
代码3
class Observable
{
private List<Observer> observers=new CopyOnWriteArrayList<Observer>(); public void addObserver(){...} public void removeObserver(){...} public void notify()
{
Iterator<Observer> itr=observers.iterator();
while(itr.hasNext()){
Observer observer=itr.next();
observer.notify();
}
return;
}
}
Observable的notify方法和代码1相同.但其不会有多线程同时操作的问题.其中的奥秘,通过分析源码可知
当CopyOnWriteArrayList添加或者删除元素时,其实现为根据当前数组重新建立一个新数组..
Java并发编程原理与实战三十四:并发容器CopyOnWriteArrayList原理与使用的更多相关文章
- Java并发编程原理与实战三十五:并发容器ConcurrentLinkedQueue原理与使用
一.简介 一个基于链接节点的无界线程安全队列.此队列按照 FIFO(先进先出)原则对元素进行排序.队列的头部 是队列中时间最长的元素.队列的尾部 是队列中时间最短的元素.新的元素插入到队列的尾部,队列 ...
- Java并发编程原理与实战三十二:ForkJoin框架详解
1.Fork/Join框架有什么用呢? ------->Fork使用来切分任务,Join是用来汇总结果.举个简单的栗子:任务是1+2+3+...+100这个任务(当然这个任务的结果有好的算法去做 ...
- Java并发编程原理与实战二十四:简易数据库连接池
public class MyDataSource { private static LinkedList<Connection> pool = new LinkedList<> ...
- Java并发编程原理与实战三十六:阻塞队列&消息队列
一.阻塞队列 1.阻塞队列BlockingQueue ---->可以理解成生产者消费者的模式---->消费者要等待到生产者生产出来产品.---->而非阻塞队列ConcurrentLi ...
- Java并发编程原理与实战三十八:多线程调度器(ScheduledThreadPoolExecutor)
在前面介绍了java的多线程的基本原理信息:线程池的原理与使用 本文对这个java本身的线程池的调度器做一个简单扩展,如果还没读过上一篇文章,建议读一下,因为这是调度器的核心组件部分. 我们如果要用j ...
- Java并发编程原理与实战三十:CountDownLatch与CyclicBarrier 区别
相信每个想深入了解多线程开发的Java开发者都会遇到CountDownLatch和CyclicBarrier,大家也在网上看到各种介绍原理,代码的,以及他们区别(应付面试)的,但是很少能讲清楚:他们到 ...
- Java并发编程原理与实战三十九:JDK8新增锁StampedLock详解
1.StampedLock是做什么的? ----->它是ReentrantReadWriteLock 的增强版,是为了解决ReentrantReadWriteLock的一些不足. 2.Ree ...
- Java并发编程原理与实战三十七:线程池的原理与使用
一.简介 线程池在我们的高并发环境下,实际应用是非常多的!!适用频率非常高! 有过使用过Executors框架的朋友,可能不太知道底层的实现,这里就是讲Executors是由ThreadPoolExe ...
- 《Java多线程编程核心技术》读后感(十四)
单例模式与多线程 立即加载/饿汉模式 立即加载就是使用类的时候已经将对象创建完毕,常见的实现办法就是直接new实例化. 立即加载/饿汉模式实在调用方法前,实例已经被创建了 package Six; p ...
随机推荐
- boolean类型的按位或||和|的区别
boolean类型既可以使用&&和||做逻辑运算,也可以使用&和|做逻辑运算,但前者是经过优化的(执行短路运算),后者未优化. 以下代码验证: 逻辑或|| public cla ...
- JPEG图像压缩算法流程详解
JPEG图像压缩算法流程详解 JPEG代表Joint Photographic Experts Group(联合图像专家小组).此团队创立于1986年,1992年发布了JPEG的标准而在1994年获得 ...
- 补发9.28“天天向上”团队Scrum站立会议
组长:王森 组员:张金生 张政 栾骄阳 时间:2016.09.28 地点:612寝 组员 已完成 未完成 王森 搭建初步原型 完善原型 张金生 更新UI设计 生成应用界面原型 张政 初步设计框架图 完 ...
- Python3.6 AES加密 pycrypto 更新为 pycryptodemo | TypeError: Object type <class 'str'> cannot be passed to C code
#!/usr/bin/env python# -*- coding:utf-8 -*-# @author: rui.xu# @update: jt.huang# 这里使用pycryptodemo库# ...
- 内网内使用https 和 使用http 建立连接的速度对比
文字版 使用https httpstat https://10.24.101.14/cwbase/web/Login.aspx --insecure Connected to HTTP/ OK Ser ...
- win7 32位 import cv2 失败 ImportError:DLL load fail:找不到指定模块
引起问题的可能性太多,这里记录比较一下比较少见的错误原因 缺少dll文件 https://www.dll-files.com/api-ms-win-downlevel-shlwapi-l1-1-0.d ...
- 第219天:Angular---过滤器
在Angular中,过滤器的功能主要是格式化数据表达式,且可以自定义过滤器.作用域(scope)主要服务于页面模板,在控制器和页面中起桥梁作用,保存模板中的数据对象,为模板中的元素提供方法和属性. 一 ...
- PHP Warning: strftime(): It is not safe to rely on the system's timezone set
当运行一些程序时,在httpd日志中会有如下警告日志: PHP Warning: strftime(): It is not safe to rely on the system's timezon ...
- oracle 11g 从 dmp 文件中导出 sql 代码 的方法.
impdp sys/password full=y dumpfile=bg.dmp nologfile=y sqlfile=bg_dmp.sql 备注: bg.dmp 是 dmp 文件, bg_d ...
- pragma指令详解(转载)
#pragma comment( comment-type [,"commentstring"] ) 该宏放置一个注释到对象文件或者可执行文件.comment-type是一个预定义 ...