CopyOnWriteArrayList 读写分离,弱一致性
为什么会有CopyOnWriteArrayList?
我们知道ArrayList和LinkedList实现的List都是非线程安全的,于是就有了Vector,它是基于ArrayList的线程安全集合,但Vector无论是add方法还是get方法都加上了synchronized修饰,当多线程读写List必须排队执行,很显然这样效率比较是低下的,那有没有一种办法让效率提升,让当读List的时候线程是异步的,当写List是同步的呢?答案是CopyOnWriteArrayList,他是读写分离的,好处是提高线程访问效率,下面我们对比下CopyOnWriteArrayList和Vector执行效率。
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch; /**
* @author :jiaolian
* @date :Created in 2021-01-18 15:28
* @description:安全list性能对比
* @modified By:
* 公众号:叫练
*/
public class SafeListTest { private static Vector<String> safeList = new Vector<>();
//private static CopyOnWriteArrayList<String> safeList = new CopyOnWriteArrayList<>(); private static CountDownLatch countDownLatch = new CountDownLatch(2); public static void main(String[] args) throws InterruptedException {
//初始化
safeList.add("叫练");
MySerive fishSerive = new MySerive();
long start = System.currentTimeMillis();
new Thread(()->{
fishSerive.read();
countDownLatch.countDown();
},"叫练读线程").start();
new Thread(()->{
fishSerive.write();
countDownLatch.countDown();
},"叫练写线程").start();
countDownLatch.await();
System.out.println("花费:"+(System.currentTimeMillis()-start));
} private static class MySerive {
//读
public void read() {
for (int i=0 ;i<1000000; i++) {
safeList.get(0);
}
} //写
public void write() {
for (int i=0 ;i<100000; i++) {
safeList.add("叫练");
}
}
}
}
如上代码:当安全集合用Vector时,执行时长是100毫秒,当安全集合用CopyOnWriteArrayList时,执行时长是5000毫秒,神码?你不是说CopyOnWriteArrayList的效率要高么?但执行情况CopyOnWriteArrayList执行的时长竟然是Vector的50倍!通过翻看源码,我们发现当CopyOnWriteArrayList写元素时是通过备份数组的方式实现的,当多线程同步激烈,数据量较大时会不停的复制数组,内存浪费严重。这就是时过长的原因!但是我们还是认可读写分离思想!

什么是弱一致性
import java.util.Iterator;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList; /**
* @author :jiaolian
* @date :Created in 2021-01-18 16:40
* @description:CopyOnWriteArrayList弱一致性
* @modified By:
* 公众号:叫练
*/
public class WeekCopyOnWriteArrayListTest { private static CopyOnWriteArrayList<String> safeList = new CopyOnWriteArrayList<>();
//private static Vector<String> safeList = new Vector<>(); public static void main(String[] args) throws InterruptedException {
safeList.add("叫");
safeList.add("练");
Iterator<String> iterator = safeList.iterator();
Thread thread = new Thread(()->{
//删除下标为0的元素
safeList.remove(0);
});
thread.start();
//主线程等待thread执行完成;
thread.join();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
} }
如上代码:主线程等待thread子线程执行完毕,循环打印safeList元素,最终执行结果如下图所示
你可能会有疑问,thread不是已经删除“叫”吗?控制台不是应该只打印一个“练”字吗?为什么还会打出“叫练”两个字,原因是main线程在执行Iterator<String> iterator = safeList.iterator();保存了元素快照,所以能看到这样的执行结果,当thread线程执行完毕后,此时JVM内存状态如下图所示!

fail-safe特性
提到fail-safe,会先提到fail-fast,字面上翻译快速失败,它是集合快速检测失败机制,防止集合不正确操作!一般情况下,如果线程通过iterator方式循环集合时,另外一个线程也修改了这个集合,我们测试下,如上述测试弱一致性的代码,将private static CopyOnWriteArrayList<String> safeList = new CopyOnWriteArrayList<>();换成private static Vector<String> safeList = new Vector<>();会发生什么情况呢?

如上图,java.util.ConcurrentModificationException,集合并发修改错误,但换成CopyOnWriteArrayList执行正常,原因是CopyOnWriteArrayList删除数据时会有集合快照。
所以他是fail-safe,而Vector是fail-fast!
总结
总结下吧,我们用代码简述说明了CopyOnWriteArrayList的读写分离,弱一致性,fail-safe,fail-safe等概念,并简述了实现原理。喜欢的请点赞加关注哦。我是叫练【公众号】,边叫边练。

CopyOnWriteArrayList 读写分离,弱一致性的更多相关文章
- Java进阶知识点6:并发容器背后的设计理念 - 锁分段、写时复制和弱一致性
一.背景 容器是Java编程中使用频率很高的组件,但Java默认提供的基本容器(ArrayList,HashMap等)均不是线程安全的.当容器和多线程并发编程相遇时,程序员又该何去何从呢? 通常有两种 ...
- Mycat读写分离、主从切换、分库分表的操作记录
系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理本身优化也是非常重要的.主从.热备.分表分库等都是系统发展迟早会遇到的技术问题问题.Mycat是一 ...
- Oceanbase读写分离方案探索与优化
[作者] 许金柱,携程资深DBA,专注于分布式数据库研究及运维. 台枫,携程高级DBA,主要负责MySQL和OceanBase的运维. [前言] 读写分离,是一种将数据库的查询操作和写入操作分离 ...
- MySQL+Amoeba实现数据库主从复制和读写分离
MySQL读写分离是在主从复制的基础上进一步通过在master上执行写操作,在slave上执行读操作来实现的.通过主从复制,master上的数据改动能够同步到slave上,从而保持了数据的一致性.实现 ...
- CYQ.Data V5 数据库读写分离功能介绍
前言 好多年没写关于此框架的新功能的介绍了,这些年一直在默默地更新,从Nuget上的记录就可以看出来: 这几天在看Java的一些东西,除了觉的Java和.NET的相似度实在太高之外,就是Java太原始 ...
- EF架构~通过EF6的DbCommand拦截器来实现数据库读写分离~终结~配置的优化和事务里读写的统一
回到目录 本讲是通过DbCommand拦截器来实现读写分离的最后一讲,对之前几篇文章做了一个优化,无论是程序可读性还是实用性上都有一个提升,在配置信息这块,去除了字符串方式的拼接,取而代之的是sect ...
- LVS+MYCAT读写分离+MYSQL同步部署手册(第三版)
1 配置MYSQL主备同步 1.1 测试环境 mysql版本:5.6.24: 操作系统内核版本:Linux-3.13-0-32 主数据库IP:192.168.10.3: 主数据库名:d ...
- LVS+MYCAT+读写分离+MYSQL主备同步部署手册
LVS+MYCAT+读写分离+MYSQL主备同步部署手册 1 配置MYSQL主备同步…. 2 1.1 测试环境… 2 1.2 配置主数据库… 2 1.2.1 ...
- MySQL高可用读写分离方案预研
目前公司有需求做MySQL高可用读写分离,网上搜集了不少方案,都不尽人意,下面是我结合现有组件拼凑的实现方案,亲测已满足要求,希望各位多提建议 :) 一. 网上方案整理(搜集地址不详...) 1 ...
随机推荐
- Swagger2配置
配置类 package top.yalong; import org.springframework.beans.factory.annotation.Value; import org.spring ...
- JSON类型解析
JSON类型解析 一.序列化和反序列化 程序中的对象,如python中的字典.列表.函数.类等,都是存在内存中,不方便传递或存储,所以需要将内存中的对象转化为文本或者文件格式,来满足传输和持久化(存储 ...
- torch中squeeze与unsqueeze用法
import torch torch中的squeeze与unsqueeze作用是去除/添加维度为1的行 例如,a=torch.randn(2,3) 那么b=a.unsqueeze(0),b为(1,2, ...
- 【Harbor学习笔记】-教你快速搭建Docker私有仓库
目录 架构图 Harbor依赖的外部组件 Harbor自有组件 核心组件 安装 1. 下载离线安装包 2. 配置 harbor.cfg (harbor.yml) 3. 启动 Harbor 安装配置问题 ...
- idea导入配置SSM项目,并进行打包
idea确实是一个功能强大的开发工具,但是配置项目太复杂,每次都要花费很长的时间在配置上. 关于SSM项目导入,配置,打包,看这篇就够了,百试不爽.
- Kafka Connect使用入门-Mysql数据导入到ElasticSearch
1.Kafka Connect Connect是Kafka的一部分,它为在Kafka和外部存储系统之间移动数据提供了一种可靠且伸缩的方式,它为连接器插件提供了一组API和一个运行时-Connect负责 ...
- Spring笔记(9) - IOC实现方式详解
IOC概念 控制反转(Inversion of Control,IOC),是面向对象编程中的一种设计原则,它建议将不需要的职责移出类,让类专注于核心职责,从而提供松散耦合,提高优化软件程序设计.它把传 ...
- ajax上传单个文件
jsp页面 <%@ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML> ...
- Could not open ServletContext resource [/WEB-INF/applicationContext.xml] 解决办法
Spring官方文档中规定,如果在上下文中没有指定contextConfigLoction配置文件的位置,则会默认去WEB-INF中去寻找对应的配置文件. 理论上classpath的默认路径是WEB- ...
- 嵌入式Linux-Bmp转jpeg
代码: /**************************************************************************** Ãû³Æ£º jpeg.c ¹ŠÄÜ ...