JUC(三)集合的线程安全
集合的线程安全
list集合线程不安全演示
List中的add方法没有添加Synchronized,因此是线程不安全的:
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
public static void main(String[] args) {
var list = new ArrayList<String>();
for (int i = 0; i < 30; i++) {
int loop = i;
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
执行会出现并发修改异常:
Exception in thread "17" java.util.ConcurrentModificationException
Vector解决
public static void main(String[] args) {
var list = new Vector<String>();
for (int i = 0; i < 300; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
Vector源码使用synchronized关键字,因此不存在线程安全问题,但是效率较低比较古老,不经常使用
Collections.synchronizedList
public static void main(String[] args) {
var list = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < 300; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
效率较低比较古老,不经常使用
JUC 解决方案:CopyOnWriteArrayList
public static void main(String[] args) {
var list = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 300; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
CopyOnWriteArrayList:写时复制技术,允许并发读取集合,但是只能单独写,即在写的时候首先复制一份集合,写完之后覆盖之前的内容
HashSet和HashMap线程不安全演示
public static void main(String[] args) {
var set = new HashSet<String>();
for (int i = 0; i < 300; i++) {
new Thread(() -> {
set.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(set);
}, String.valueOf(i)).start();
}
}
public static void main(String[] args) {
var map = new HashMap<String, String>();
for (int i = 0; i < 300; i++) {
int loop = i;
new Thread(() -> {
map.put(String.valueOf(loop), UUID.randomUUID().toString().substring(0, 8));
System.out.println(map);
}, String.valueOf(i)).start();
}
}
JUC 解决方案:CopyOnWriteArrayList
public static void main(String[] args) {
var set = new CopyOnWriteArraySet<String>();
for (int i = 0; i < 300; i++) {
new Thread(() -> {
set.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(set);
}, String.valueOf(i)).start();
}
}
JUC 解决方案:ConcurrentHashMap
public static void main(String[] args) {
var map = new ConcurrentHashMap<String, String>();
for (int i = 0; i < 300; i++) {
int loop = i;
new Thread(() -> {
map.put(String.valueOf(loop), UUID.randomUUID().toString().substring(0, 8));
System.out.println(map);
}, String.valueOf(i)).start();
}
}
JUC(三)集合的线程安全的更多相关文章
- JUC源码分析-线程池篇(三)ScheduledThreadPoolExecutor
JUC源码分析-线程池篇(三)ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor.它主要用来在 ...
- JUC源码分析-线程池篇(三)Timer
JUC源码分析-线程池篇(三)Timer Timer 是 java.util 包提供的一个定时任务调度器,在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次. 1. Ti ...
- Java并发编程之set集合的线程安全类你知道吗
Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥Java:kagejava)并发编程学习> ...
- Java中的集合和线程安全
通过Java指南我们知道Java集合框架(Collection Framework)如何为并发服务,我们应该如何在单线程和多线程中使用集合(Collection). 话题有点高端,我们不是很好理解.所 ...
- JUC源码分析-线程池篇(一):ThreadPoolExecutor
JUC源码分析-线程池篇(一):ThreadPoolExecutor Java 中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池 ...
- 学习javascript数据结构(三)——集合
前言 总括: 本文讲解了数据结构中的[集合]概念,并使用javascript实现了集合. 原文博客地址:学习javascript数据结构(三)--集合 知乎专栏&&简书专题:前端进击者 ...
- 多线程(三) java中线程的简单使用
java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依 ...
- C# Synchronized 和 SyncRoot 实现线程同步的源码分析及泛型集合的线程安全访问
转载:http://blog.csdn.net/zztfj/article/details/5640889 Synchronized vs SyncRoot 我们知道,在.net的一些集合类型中,譬如 ...
- Python 多线程、多进程 (三)之 线程进程对比、多进程
Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.多线程与多进 ...
- C# 线程手册 第三章 使用线程 实现一个数据库连接池(实战篇)
在企业级软件开发过程中,为了改善应用程序的性能需要通常使用对象池来控制对象的实例化.例如,在我们每次需要连接一个数据库时都需要创建一个数据库连接,而数据库连接是非常昂贵的对象.所以,为了节省为每次数据 ...
随机推荐
- 打开CMD的方式
打开Cmd的方式: 1.开始+系统+命令提示符 2.Win键+R 3.在任意文件夹下,按住Shift键+鼠标右键点击,在此处打开命令行窗口 4.资源管理的地址栏前面加上Cmd路径 管理员运行方式 :系 ...
- JAVA设计模式及其设计原则
设计模式: 设计模式是一套被反复使用的.多数人知晓的.经过分类编目的.代码设计经验的总结. 单例模式:在一个jvm虚拟机,要创建的对象控制成独一份:举例:统计单台虚拟机内的用户在线数 package ...
- 国际化vue-i18n 向语言包中传入参数
模板 <span>{{$t('el.table.total', { pagetotal: 123 })}}</span> js代码中 this.$t('el.table.num ...
- org.nutz.http.Http忽略https SSL证书验证
访问的是一个https get请求,报错需要SSL证书验证,以下方法直接跳过 boolean check = Http.disableJvmHttpsCheck(); // 忽略https的证书检查
- pntia7-7 软硬车厢交替排列 (40 分)
7-7 软硬车厢交替排列 (40 分) 设车辆厂生产了硬座车厢和软座车厢共n节(混合在一起),要求使用队列的基本操作,编程实现所有硬座车厢和所有软座车厢交替排列. 例如硬座车厢用H来表示,软座车厢用S ...
- 复制文件到U盘提示“一个意外错误使您无法复制该文件”处理办法
运行cmd 运行 chkdsk H(U盘所在盘符):/f 即可
- conceive of NIO
设想需要传递数据的两端 输入端与接收端 1.字符存储格式不同,需unicode 2.保存格式不通,需格式化 传输数据时 1.需要介质(通道) 2.需要对数据进行输入端接收端都能识别的格式. 3.需要将 ...
- bbswitch与bumblebee配合使用
!建议查阅并使用archwiki的bumblebee方案 ! 安装NONFREE驱动 1.在终端中输入以下命令来检查已安装的驱动版本(我这次装manjaro是hybird440) inxi -G 2. ...
- NX二次开发 版本通用方法
对于用C++做NX二次开发,随着NX的版本变更,二开所用的函数也会有相应的更新调整,生成的DLL不能跨版本运行,报错率极高,甚至不能加载.折腾了好久找到三种方法: 1.纯使用C++的代码开发或者尽可能 ...
- 9. PEP8规范
1. 每一级缩进4个空格 2. 续行时缩进要比正常行多缩进, 要能明显看出是续行的 3. 每一行最多79个字符 4. 函数和类定义时在前后加2个空行, 类内接口在定义时, 前后加1个空行 5. 二元运 ...