Java JUC中操作List安全类的集合案例
作者:专注写bug 发布时间:2022-10-28 11:09:31
不安全的集合
在单线程应用中,通常采取new ArrayList(),指定一个List集合,用于存放可重复的数据。
但在多线程下,往往会出现意想不到的问题,代码如下所示:
import java.util.*;
public class ListTest {
public static void main(String[] args) throws InterruptedException {
// 创建list集合
//List<String> lists = Arrays.asList("1", "2", "3");
// 不安全
List<String> lists = new ArrayList<>();
// 开启十个线程增加数据
for (int i = 1; i <= 40; i++) {
new Thread(()->{
lists.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName()+"=="+lists);
},String.valueOf(i)).start();
}
}
}
其运行结果如下所示:
多线程操作同一集合对象信息,往往会出现java.util.ConcurrentModificationException异常报错信息。
Java中提供的安全措施
在java语言中,提供了一种新的List集合,java.util.Vector类,具体看下列代码:
import java.util.*;
public class ListTest {
public static void main(String[] args) throws InterruptedException {
// 创建list集合
//List<String> lists = Arrays.asList("1", "2", "3");
// 不安全
//List<String> lists = new ArrayList<>();
List<String> lists = new Vector<>();
// 开启十个线程增加数据
for (int i = 1; i <= 40; i++) {
new Thread(()->{
lists.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName()+"=="+lists);
},String.valueOf(i)).start();
}
}
}
运行日志如下所示:
不会出现java.util.ConcurrentModificationException报错信息。
为什么能保证数据的安全操作?
采取了 synchronized 针对方法执行调用者加锁,保证add操作的多线程安全性!
JUC下的安全List集合
在JUC包下,提供有以下几种创建安全集合的方式。
方式一:Collections.synchronizedList(new ArrayList<>());
import java.util.*;
public class ListTest {
public static void main(String[] args) throws InterruptedException {
List<String> lists = Collections.synchronizedList(new ArrayList<>());
// 开启十个线程增加数据
for (int i = 1; i <= 40; i++) {
new Thread(()->{
lists.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName()+"=="+lists);
},String.valueOf(i)).start();
}
}
}
查看底层源码实现逻辑
判断传入的 list 集合类型,判断类型是否为 java.util.RandomAccess,如果是则采取java.util.Collections.SynchronizedRandomAccessList构造集合,如果不是则采取java.util.Collections.SynchronizedList构造集合。
源码中对应的add操作逻辑如下所示:
采取synchronized同步代码块的方式,对数据的add操作实现加锁!
方式二:new CopyOnWriteArrayList();
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class ListTest {
public static void main(String[] args) throws InterruptedException {
List<String> lists = new CopyOnWriteArrayList<>();
// 开启十个线程增加数据
for (int i = 1; i <= 40; i++) {
new Thread(()->{
lists.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName()+"=="+lists);
},String.valueOf(i)).start();
}
}
}
源码中的介绍如下:
显而易见,其逻辑如下所示:
调用add方法后,拿到java.util.concurrent.locks.ReentrantLock对象信息。
调用 lock.lock() 拿到锁!
将原数组对象copy操作,并创建原数组大小+1的新数组。
将新数据放入新数组中。
任何操作finally,都进行锁的释放!
性能方面
JUC包下的Lock操作,都比synchronized性能更好!
到此这篇关于JUC中操作List安全类的集合案例的文章就介绍到这了,更多相关JUC中List安全类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
来源:https://blog.csdn.net/qq_38322527/article/details/114703142
猜你喜欢
- 学习java的人都知道spring,springMVC,mybatis等框架,像structs2这样的框架是基于servlet以外实现的,而
- 记得上学的时候学习英语,每个英语老师说到英语翻译的时候都会说英语翻译要做到“信、达、雅”。如今做了一名程序员竟然体会我还是想用这三种境界来要
- 本文研究的主要是Hibernate hql查询的相关内容,具体如下。HQL介绍Hibernate语言查询(Hibernate Query L
- springboot 无法自动装配@Autowired 报错:无法自动装配基本上是因为1、项目里有类似mybatis @Mapper这种第三
- 总结并复现了一下Unsafe在安全领域的一些应用0 前言unsafe里面有很多好用的方法,比如allocateInstance可以直接创建实
- 本文实例为大家分享了spring mvc实现文件上传与下载功能的具体代码,供大家参考,具体内容如下文件上传在pom.xml中引入spring
- 本文实例讲述了C#检查字符串是否是合法URL地址的方法。分享给大家供大家参考。具体实现方法如下:protected string HTTPC
- 前言本文我们主要实战Mybatis官方的代码生成器:Mybatis Generator(MBG),掌握它以后,可以简化大部分手写代码,我们只
- 1. 添加maven依赖包<dependency> <groupId>org.apache.calcit
- ftp/sftp概念及搭建ftp是一种文件传输协议,让客户端和服务端能够互相传递文件,图片等数据;方便快捷;sftp是ssh file tr
- 1. 前言ResultSetMetaData 叫元数据,是数据库 列对象,以列为单位封装为对象。元数据,指的是其包含列名,列值,列类型,列长
- BeanDefinitionRegistryPostProcessor概述可以看到BeanDefinitionRegistryPostPro
- 本文实例为大家分享了Java实现马踏棋盘的具体代码,供大家参考,具体内容如下马在某个点最多可能有8种走法,用递归和回溯实现。注:代码中,查找
- 1.相关概念Spring Boot 默认为我们提供了静态资源处理,使用 WebMvcAutoConfiguration 中的配置各种属性。建
- 本文研究的主要是ConcurrentMap.putIfAbsent(key,value)用法的相关内容,具体如下。业务上经常会遇到有这种场景
- 前言为了减少日志频繁打印带来的性能影响,线上环境设置的日志级别一般都相对较高。而当出现生产问题需要排查的时候,可能需要适当降低日志级别(例如
- 在application.properties中填写中文信息,在读取该文件时会出现中文乱码问题。比如:application.propert
- 一、背景项目中肯定会遇到异步调用其他方法的场景,比如有个计算过程,需要计算很多个指标的值,但是每个指标计算的效率快慢不同,如果采用同步执行的
- 本文实例为大家分享了C#实现贪吃蛇小游戏的具体代码,供大家参考,具体内容如下之前一直想写一个贪吃蛇小游戏,上个周末终于有时间做了一个,现在和
- 饿汉式立即加载防止new对象,构造私有,写一个公共的方法返回对象占用空间,线程安全public class Singleton { &nbs