集合的线程安全

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(三)集合的线程安全的更多相关文章

  1. JUC源码分析-线程池篇(三)ScheduledThreadPoolExecutor

    JUC源码分析-线程池篇(三)ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor.它主要用来在 ...

  2. JUC源码分析-线程池篇(三)Timer

    JUC源码分析-线程池篇(三)Timer Timer 是 java.util 包提供的一个定时任务调度器,在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次. 1. Ti ...

  3. Java并发编程之set集合的线程安全类你知道吗

    Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥Java:kagejava)并发编程学习> ...

  4. Java中的集合和线程安全

    通过Java指南我们知道Java集合框架(Collection Framework)如何为并发服务,我们应该如何在单线程和多线程中使用集合(Collection). 话题有点高端,我们不是很好理解.所 ...

  5. JUC源码分析-线程池篇(一):ThreadPoolExecutor

    JUC源码分析-线程池篇(一):ThreadPoolExecutor Java 中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池 ...

  6. 学习javascript数据结构(三)——集合

    前言 总括: 本文讲解了数据结构中的[集合]概念,并使用javascript实现了集合. 原文博客地址:学习javascript数据结构(三)--集合 知乎专栏&&简书专题:前端进击者 ...

  7. 多线程(三) java中线程的简单使用

    java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依 ...

  8. C# Synchronized 和 SyncRoot 实现线程同步的源码分析及泛型集合的线程安全访问

    转载:http://blog.csdn.net/zztfj/article/details/5640889 Synchronized vs SyncRoot 我们知道,在.net的一些集合类型中,譬如 ...

  9. Python 多线程、多进程 (三)之 线程进程对比、多进程

    Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.多线程与多进 ...

  10. C# 线程手册 第三章 使用线程 实现一个数据库连接池(实战篇)

    在企业级软件开发过程中,为了改善应用程序的性能需要通常使用对象池来控制对象的实例化.例如,在我们每次需要连接一个数据库时都需要创建一个数据库连接,而数据库连接是非常昂贵的对象.所以,为了节省为每次数据 ...

随机推荐

  1. CSS 常用样式-盒模型属性

    盒模型又叫框模型,包含了五个用来描述盒子位置.尺寸的属性,分别是宽度 width.高度 height.内边距 padding. 边框 border.外边距 margin. 常见盒模型区域: • 盒模型 ...

  2. Sql Server新建一个只读权限的用户

    1,新建只能访问某一个表的只读用户. --添加只允许访问指定表的用户: exec sp_addlogin '用户名','密码','默认数据库名' --添加到数据库 exec sp_grantdbacc ...

  3. OSIDP-线程-04

    进程和线程 进程具有两个相互独立的特点: 1.资源所有权:进程包括存放进程映像的虚拟地址空间,具有对资源的控制权. 2.调度/执行:进程具有运行状态和优先级,是可被 OS 调度和分派的实体. 通常将分 ...

  4. 图模配置文件之 mdimport.ini

    mdimport.ini文件是图模导入中最最最关键的一个配置文件,其中既包含图模导入程序model_import.model_debug相关的配置,也包含红黑图管理界面显示及应用相关的配置信息,还包含 ...

  5. This will upgrade your R installation.

    sudo add-apt-repository ppa:marutter/rrutter sudo apt update sudo apt full-upgrade

  6. [扫描工具]dirsearch简单使用

    [扫描工具]dirsearch简单使用 dirsearch是一个python开发的目录扫描工具.和我们平时使用的dirb.御剑之类的工具一样,就是为了扫描网站的敏感文件和目录从而找到突破口. 安装: ...

  7. FastReport OpenSource发布到Linux上的准备

    一.安装libgdiplus(libgdiplus是一个Mono库,用于对非Windows操作系统提供GDI+兼容的API)   apt-get install build-essential lib ...

  8. vite不能用@做为路径的解决方法

    vite创建vue3后,发现原来用@做为路径的不能用了,报错信息是 Internal server error: Failed to resolve import "@ 在网上查了一下资料, ...

  9. 手把手带你玩转Linux

    今天这篇文章带你走进Linux世界的同时,带你手把手玩转Linux,加深对Linux系统的认识. 一.搞好Linux工作必须得不断折腾,说白了,只是动手力量必须强.我在初学Linux的那片,家中三台计 ...

  10. RPA的数字化标签

    随着中国经济的飞速发展,"人口红利"也正在不断消失,在过去几十年中,我们已经看到了各种智能化.自动化技术的进步对各行各业产生的巨大影响.但在现代金融行业中,仍然有许多重复.简单.繁 ...