ArrayList为什么是线程不安全的
首先需要了解什么是线程安全:线程安全就是说多线程访问同一代码(对象、变量等),不会产生不确定的结果。 既然说ArrayList是线程不安全的,那么在多线程中操作一个ArrayList对象,则会出现不确定的结果。具体是怎样不确定,请看测试下面这段代码(在此测试ArrayList的add方法):
public class ArrayListInThread implements Runnable{
//线程不安全
private List threadList = new ArrayList();
//线程安全
//private List threadList = Collections.synchronizedList(new ArrayList());
@Override
public void run() {
try {
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
//把当前线程名称加入list中
threadList.add(Thread.currentThread().getName());
}
public static void main(String[] args) throws InterruptedException{
ArrayListInThread listThread = new ArrayListInThread();
for(int i = 0; i < 100; i++){
Thread thread = new Thread(listThread, String.valueOf(i));
thread.start();
}
//等待子线程执行完
Thread.sleep(2000);
System.out.println(listThread.threadList.size());
//输出list中的值
for(int i = 0; i < listThread.threadList.size(); i++){
if(listThread.threadList.get(i) == null){
System.out.println();;
}
System.out.print(listThread.threadList.get(i) + " ");
}
}
}
执行几次会发现结果不一样,甚至有时会出现ArrayIndexOutOfBoundsException,贴出几次执行的结果:
结果一:
结果二:
结果三:
以上执行结果说明ArrayList确实是线程不安全的,然后我们从线程并发的角度分析,为何会出现这样的结果:
首先,我们先来看一下ArrayList中的add方法是如何实现的
//添加元素e
public boolean add(E e) {
// 确定ArrayList的容量大小
ensureCapacity(size + 1); // Increments modCount!!
// 添加e到ArrayList中
elementData[size++] = e;
return true;
}
// 确定ArrarList的容量。
// 若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=“(原始容量x3)/2 + 1”
public void ensureCapacity(int minCapacity) {
// 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的
modCount++;
int oldCapacity = elementData.length;
// 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1”
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
//如果还不够,则直接将minCapacity设置为当前容量
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
结果中,有的值没有出现(结果一中3没有出现),有的出现了null值,这是由于赋值时出现了覆盖。赋值语句为:elementData[size++] = e,这条语句可拆分为两条:
1. elementData[size] = e;
2. size ++;
假设A线程执行完第一条语句时,CPU暂停执行A线程转而去执行B线程,此时ArrayList的size并没有加一,这时在ArrayList中B线程就会覆盖掉A线程赋的值,而此时,A线程和B线程先后执行size++,便会出现值为null的情况;至于结果三中出现的ArrayIndexOutOfBoundsException异常,
则是A线程在执行ensureCapacity(size+1)后没有继续执行,此时恰好minCapacity等于oldCapacity,B线程再去执行,同样由于minCapacity等于oldCapacity,ArrayList并没有增加长度,B线程可以继续执行赋值(elementData[size] = e)并size ++也执行了,此时,CPU又去执行A线程的赋值操作,由于size值加了1,size值大于了ArrayList的最大长度,
因此便出现了ArrayIndexOutOfBoundsException异常。
既然ArrayList是线程不安全的,但如果需要在多线程中使用,可以采用list<Object> list =Collections.synchronizedList(new ArrayList<Object>)来创建一个ArrayList对象。
原文:https://blog.csdn.net/zhangxin961304090/article/details/46804065
ArrayList为什么是线程不安全的的更多相关文章
- Day10_53_Collections.synchronizedList() 将Arraylist集合转换为线程安全的集合
将Arraylist集合转换为线程安全的集合 import java.util.ArrayList; import java.util.Collections; import java.util.Li ...
- ArrayList如何实现线程安全
一:使用synchronized关键字,这个大家应该都很熟悉了,不解释了: 二:使用Collections.synchronizedList();使用方法如下: 假如你创建的代码如下:List< ...
- ArrayList如何保证线程安全
ArrayList是线程不安全的,轻量级的.如何使ArrayList线程安全? 1.继承Arraylist,然后重写或按需求编写自己的方法,这些方法要写成synchronized,在这些synchro ...
- 论 ArrayList如何实现线程安全
一:使用synchronized关键字 二:使用Collections.synchronizedList(); 假如你创建的代码如下:List<Map<String,Object>& ...
- 在JAVA中ArrayList如何保证线程安全
[b]保证线程安全的三种方法:[/b]不要跨线程访问共享变量使共享变量是final类型的将共享变量的操作加上同步一开始就将类设计成线程安全的, 比在后期重新修复它,更容易.编写多线程程序, 首先保证它 ...
- 为什么ArrayList、LinkedList线程不安全,Vector线程安全
ArrayList源码 public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! ele ...
- ArrayList/Vector的原理、线程安全和迭代Fail-Fast
疑问 * ArrayList是非线程非安全的,具体是指什么?具体会产生什么问题?* ArrayList的内部原理是什么?为什么可以动态扩容?* Vector是线程安全的,具体是如何实现的?为什么不再推 ...
- 为什么说ArrayList是线程不安全的?
一.概述 对于ArrayList,相信大家并不陌生.这个类是我们平时接触得最多的一个列表集合类. 面试时相信面试官首先就会问到关于它的知识.一个经常被问到的问题就是:ArrayList是否是线程安全的 ...
- 容器之List接口下各实现类(Vector,ArrayList 和LinkedList)的线程安全问题
Vector .ArrayList 和LinkedList都是List接口下的实现类,但是他们之间的区别和联系是什么呢? 首先: 然后: 如果您仅仅想知道结论,那么可以关闭了. 下面我讨论讨论为什么. ...
随机推荐
- 诺依/RuoYi开源系统搭建总结
问题一:从{码云}下载下来看,输入项目编码不过 解决方法: 加入下列依赖,版本要和下载下来的{spring-boot-dependencies}一致.不一致就会报问题2: <parent> ...
- Salesforce学习之路-developer篇(五)一文读懂Aura原理及实战案例分析
1. 什么是Lightning Component框架? Lightning Component框架是一个UI框架,用于为移动和台式设备开发Web应用程序.这是一个单页面Web应用框架,用于为Ligh ...
- 【ABAP系列】SAP ABAP7.40新语法简介第一篇
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP7.40新语法简 ...
- 【生成树趣题】CF723F st-Spanning Tree
题目传送门 题意: 给定一个n个点m条边的无向联通图,没有重边和自环.给定s和t,求一棵生成树,使得s,t的度数不超过ds,dt.若有解,输出“Yes”和方案(多组方案输出任意一组),若无解,输出“N ...
- jqueryweui关于switch css与js结合
.invoice_wrapper{ .comm_con{ .weui-switch-cp{ .weui-switch-cp__box{ height:0.4rem; margin:0.25rem 0; ...
- elasticsearch-analysis-ik windows 环境 IK 中文分词器 的 下载 和 安装
1,下载插件压缩包(本地测试建议用迅雷下,生产用的绝对不要用迅雷下),链接地址:https://github.com/medcl/elasticsearch-analysis-ik/releases/ ...
- windows qt 使用openssl API
1.下载安装openssl http://dl.pconline.com.cn/download/355862-1.html 版本: OpenSSL(Win32) 1.0.1g 2.配置QT项目文件, ...
- Selenium+PhantomJs 爬取网页内容
利用Selenium和PhantomJs 可以模拟用户操作,爬取大多数的网站.下面以新浪财经为例,我们抓取新浪财经的新闻版块内容. 1.依赖的jar包.我的项目是普通的SSM单间的WEB工程.最后一个 ...
- 小记---------网页采集之Jsoup
Jsoup是一款Java解析器,相当于httpClient解析器 功能:①:从一个URL,文件或字符串中解析HTML ②:使用DOM或CSS选择器来查找.取出数据 ...
- python爬取天气后报网
前言 大二下学期的大数据技术导论课上由于需要获取数据进行分析,我决定学习python爬虫来获取数据.由于对于数据需求量相对较大,我最终选择爬取 天气后报网,该网站可以查询到全国各地多年的数据,而且相对 ...