java juc作者_Java面试之JUC系列:Collection线程不安全的举例
Collection线程不安全的举例
前言
1、当我们执行下面语句的时候,底层进行了什么操作
new ArrayList();
底层创建了一个空的数组,伴随着初始值为10
当执行add方法后,如果超过了10,那么会进行扩容,扩容的大小为原值的一半,也就是5个,使用下列方法扩容
Arrays.copyOf(elementData, netCapacity)
单线程环境下
单线程环境的ArrayList是不会有问题的
public class ArrayListNotSafeDemo {
public static void main(String[] args) {
Listlist = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
for(String element : list) {
System.out.println(element);
}
}
}
多线程环境
为什么ArrayList是线程不安全的?因为在进行写操作的时候,方法上为了保证并发性,是没有添加synchronized修饰,所以并发写的时候,就会出现问题
当我们同时启动30个线程去操作List的时候
/**
* 集合类线程不安全举例
* @author: 陌溪
* @create: 2020-03-12-20:15
*/
public class ArrayListNotSafeDemo {
public static void main(String[] args) {
Listlist = new ArrayList<>();
for (int i = 0; i < 30; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
}
这个时候出现了错误,也就是java.util.ConcurrentModificationException
这个异常是 并发修改的异常
解决方案
方案一:Vector
第一种方法,就是不用ArrayList这种不安全的List实现类,而采用Vector,线程安全的
关于Vector如何实现线程安全的,而是在方法上加了锁,即synchronized
这样就每次只能够一个线程进行操作,所以不会出现线程不安全的问题,但是因为加锁了,导致并发性基于下降
方案二:Collections.synchronized()
Listlist = Collections.synchronizedList(new ArrayList<>());
采用Collections集合工具类,在ArrayList外面包装一层 同步 机制
方案三:采用JUC里面的方法
CopyOnWriteArrayList:写时复制,主要是一种读写分离的思想
写时复制,CopyOnWrite容器即写时复制的容器,往一个容器中添加元素的时候,不直接往当前容器Object[]添加,而是先将Object[]进行copy,复制出一个新的容器object[] newElements,然后新的容器Object[] newElements里添加原始,添加元素完后,在将原容器的引用指向新的容器 setArray(newElements);这样做的好处是可以对copyOnWrite容器进行并发的度,而不需要加锁,因为当前容器不需要添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器
就是写的时候,把ArrayList扩容一个出来,然后把值填写上去,在通知其他的线程,ArrayList的引用指向扩容后的
查看底层add方法源码
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
首先需要加锁
final ReentrantLock lock = this.lock;
lock.lock();
然后在末尾扩容一个单位
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
然后在把扩容后的空间,填写上需要add的内容
newElements[len] = e;
最后把内容set到Array中
HashSet线程不安全
CopyOnWriteArraySet
底层还是使用CopyOnWriteArrayList进行实例化
HashSet底层结构
同理HashSet的底层结构就是HashMap
但是为什么我调用 HashSet.add()的方法,只需要传递一个元素,而HashMap是需要传递key-value键值对?
首先我们查看hashSet的add方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
我们能发现但我们调用add的时候,存储一个值进入map中,只是作为key进行存储,而value存储的是一个Object类型的常量,也就是说HashSet只关心key,而不关心value
HashMap线程不安全
同理HashMap在多线程环境下,也是不安全的
public static void main(String[] args) {
Mapmap = new HashMap<>();
for (int i = 0; i < 30; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 8));
System.out.println(map);
}, String.valueOf(i)).start();
}
}
解决方法
1、使用Collections.synchronizedMap(new HashMap<>());
2、使用 ConcurrentHashMap
Mapmap = new ConcurrentHashMap<>();
java juc作者_Java面试之JUC系列:Collection线程不安全的举例相关推荐
- java面试常考_JAVA面试常考系列十
JAVA面试常考系列十 题目一 Servlet是什么? Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,是用Java编写的服务器端程序,主要的 ...
- java arraylist 初始化_Java面试整理-基础篇8.集合1
1.Java中常见的集合及其关系? 2.ArrayList.LinkedList.Vector的区别? 1. LinkedList.ArrayList.Vector都是List接口的子类:Linked ...
- 线程 sleep 取消_Java面试集锦:25道线程类相关面试题与答案(下)
26. 并发编程三要素? 1)原子性 原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行. 2)可见性 可见性指多个线程操作一个共享变量时,其中一个线程对 ...
- java 取余_JAVA面试解析(有赞)
一面引言 说在前面的话: 本文适合人群:急等着换工作的人 我承认刷面试题很有用的,纵观几年来的JAVA面试题,你会发现每家都差不多.比如,你仔细观察,你会发现,HashMap的出现几率未免也太高了吧! ...
- java lock 对象_Java并发编程锁系列之ReentrantLock对象总结
Java并发编程锁系列之ReentrantLock对象总结 在Java并发编程中,根据不同维度来区分锁的话,锁可以分为十五种.ReentranckLock就是其中的多个分类. 本文主要内容:重入锁理解 ...
- java 模块 分工_Java秒杀系统实战系列~构建SpringBoot多模块项目
摘要:本篇博文是"Java秒杀系统实战系列文章"的第二篇,主要分享介绍如何采用IDEA,基于SpringBoot+SpringMVC+Mybatis+分布式中间件构建一个多模块的项 ...
- java自我介绍_JAVA面试技巧之自我介绍
[如何进行自我介绍] 自我介绍这个问题,不用多说了,面试必定会问!如果想要在自我介绍的时候就能够打动面试官,吸引面试官对我们的兴趣,那么像我们这种接受过Java培训的程序员的自我介绍当然不能和应届生或 ...
- java笔试题_Java面试才到笔试就没有然后了?快来签收,高频笔试57题及解答
前言 很多人面试之前,可能没有在互联网公司工作过或者说工作过但年头较短,不知道互联网公司技术面试都会问哪些问题? 再加上可能自己准备也不充分,去面试没几个回合就被面试官几个问题打蒙了,甚至笔试都过不了 ...
- java基本特性_Java面试总结之Java基础
无论是工作多年的高级开发人员还是刚入职场的新人,在换工作面试的过程中,Java基础是必不可少的面试题之一.能不能顺利通过面试,拿到自己理想的offer,在准备面试的过程中,Java基础也是很关键的.对 ...
最新文章
- CUDA Samples: Calculate Histogram(atomicAdd)
- 201671010417 金振兴 词频统计软件项目报告
- 创建ContentProvider的详细步骤
- mqtt协议视频教程_MQTT协议教程
- Tomcat 6.0 日志处理
- java实现linkstring,【JAVA SE基础篇】32.String类入门
- SolrCloud zookeeper节点信息
- ThreadPoolExcutor 线程池 异常处理 (上篇)
- 只可顺守不可逆取书法_闲章不“闲”
- 数据结构之基于Java的链接栈实现
- Flutter游戏:简单规则与结束页
- Centos7部署轻量级自动化运维工具pssh (亲测)
- 如何排查Oracle表空间不足问题
- 信息技术 用计算机做科学实验报告,8.用计算机做科学实验.doc
- 国开计算机实操题操作,国开大学计算机实操答案一.
- Amoeba:开源的分布式数据库Porxy解决方案
- rtthread spiflash (w25q64)
- 怎么制作鸿蒙系统启动盘,开物成务,鸿蒙操作系统全景解构
- 毕设第三周(12月19日——12月25日)
- 使用Python调用mdx字典文件进行查词
热门文章
- c语言电脑报价系统,笔记本电脑销售管理系统-C语言-课程设计-实验.doc
- 压缩 : tar . giz
- 《乌合之众》--Agree with something
- azure mysql 配置,php-在Azure云服务上配置WordPress以通过SSL连接到Azure MySQL
- 好用的影音APP要关注哪些方面和功能?
- 20171025-迷恋小概率事件
- python学习记录1(基础知识)
- 过了这么多年,我终于学会跟Office说再见
- error: expected constructor, destructor, or type conversion before ‘(’ token PLUGINLIB_DECLARE_CLAS
- ——————猿小王日记——————