集合的线程安全

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. centos7 升级gcc

    #安装gcc yum install -y gcc-c++ autoconf automake ​ #centos7 默认的 gcc 默认是4.8.5,版本小于 5.3 无法编译,需要先安装gcc新版 ...

  2. json for python学习笔记

    1.json作用 存储数据与数据传输 2.python中的json可以在代码中用字符串表示,字符串内部类似于字典 如: json1 = '{"name":"Bob&quo ...

  3. 钉钉扫码登录第三方,appSecret签名算法(附包名)

    包名 import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.crypto.Mac; ...

  4. Cookie会话跟踪技术

    cookie是什么 cookie 也叫 HTTPCookie,是客户端与服务器端进行会话(session)使用的一个能够在浏览器本地化存储的技术. cookie就是为了存储 sessionID而诞生. ...

  5. CentOS7 安裝DHCP服務並啟用DHCP failover

    1. 安裝dhcp服務 yum install -y dhcp 2. host1 vi /etc/dhcp/dhcpd.failover failover peer "dhcpfailove ...

  6. JSP环境搭建及入门 和 虚拟路径和虚拟主机

    Jsp:是一个动态网页,而不是静态网页 html,css,js,Jquery:是静态网页 动态网页是随着,时间,地点,用户操作,而改变 静态不需要jsp 动态是需要的 BS 可以通过浏览器直接访问浏览 ...

  7. SqlServer提示对象名无效

    执行脚本 exec sp_msforeachtable "sp_changeobjectowner '?','dbo'"

  8. Sqoop从MySQL向Hive增量式导入数据报错:Exception in thread "main" java.lang.NoClassDefFoundError: org/json/JSONObject

    1.问题描述: (1)问题示例: Step1:创建作业: [Hadoop@master TestDir]$ sqoop job \> --create myjob_1 \> -- impo ...

  9. Linux挂载U盘报错:mount: unknown filesystem type 'ntfs'

    原因:由于Linux上无法识别NTFS格式的分区的原因 解决方法:安装 ntfs-3g 1.下载:wget https://tuxera.com/opensource/ntfs-3g_ntfsprog ...

  10. bat将多个文件夹下内容合并到一个文件夹下

    for /f "delims=" %%p in ('dir /b/ad') do copy %%p\*.* d:\all\ pause 目标文件夹 d:\all\ 最好不用中文目录