出场率比较高的一道多线程安全面试题

转载自  出场率比较高的一道多线程安全面试题

下面这个问题是 Java 程序员面试经常会遇到的吧。

工作一两年的应该都知道 ArrayList 是线程不安全的,要使用线程安全的就使用 Vector,这也是各种 Java 面试宝典里面所提及的,可能很多工作好几年的程序员都停留在这个知识面上。

先说说为什么 ArrayList 是线程不安全的吧,来看以下的代码。

  1. /**

  2. * 微信公众号:Java技术栈

  3. */

  4. public class TestArrayList {

  5.  

  6.    private static List<Integer> list = new ArrayList<>();

  7.  

  8.    public static void main(String[] args) throws InterruptedException {

  9.        for (int i = 0; i < 10; i++) {

  10.            testList();

  11.            list.clear();

  12.        }

  13.    }

  14.  

  15.    private static void testList() throws InterruptedException {

  16.        Runnable runnable = () -> {

  17.            for (int i = 0; i < 10000; i++) {

  18.                list.add(i);

  19.            }

  20.        };

  21.  

  22.        Thread t1 = new Thread(runnable);

  23.        Thread t2 = new Thread(runnable);

  24.        Thread t3 = new Thread(runnable);

  25.  

  26.        t1.start();

  27.        t2.start();

  28.        t3.start();

  29.  

  30.        t1.join();

  31.        t2.join();

  32.        t3.join();

  33.  

  34.        System.out.println(list.size());

  35.    }

  36.  

  37. }

这是它的输出结果,我们期望的结果应该都是:30000,然后并不是,这就是传说中的多线程并发问题了。

  1. Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 15786

  2.    at java.base/java.util.ArrayList.add(ArrayList.java:468)

  3.    at java.base/java.util.ArrayList.add(ArrayList.java:480)

  4.    at com.test.thread.TestArrayList.lambda$testList$0(TestArrayList.java:23)

  5.    at java.base/java.lang.Thread.run(Thread.java:844)

  6. 20332

  7. 16100

  8. 14941

  9. 23749

  10. 15631

  11. 22118

  12. 27417

  13. 30000

  14. 28691

  15. 27843

现象分析

从以上结果可以总结出 ArrayList 在并发情况下会出现的几种现象。

1、发生 ArrayIndexOutOfBoundsException 异常;

  1. private void add(E e, Object[] elementData, int s) {

  2.    if (s == elementData.length)

  3.        elementData = grow();

  4.    elementData[s] = e;

  5.    size = s + 1;

  6. }

定位到异常所在源代码,毫无疑问,问题是出现在多线程并发访问下,由于没有同步锁的保护,造成了 ArrayList 扩容不一致的问题。

2、程序正常运行,输出了少于实际容量的大小;

这个也是多线程并发赋值时,对同一个数组索引位置进行了赋值,所以出现少于预期大小的情况。

3、程序正常运行,输出了预期容量的大小;

这是正常运行结果,未发生多线程安全问题,但这是不确定性的,不是每次都会达到正常预期的。

解决方案

既然这样,那么在高并发情况下,使用什么样的列表集合保护线程安全呢?回到文章最开始的地方,使用 Vector,还有别的吗?当然有,篇幅有限,请各位看官期待后续文章。

另外,像 HashMap, HashSet 等都有类似多线程安全问题,在多线程并发环境下避免使用这种集合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327183.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JDBC连接数据库教程,postgreSQL

https://blog.csdn.net/jg15617651654/article/details/63262456/ JDBC连接数据库教程&#xff0c;postgreSQL 流年你奈我何 2017-03-18 17:17:43 17389 收藏 4 分类专栏&#xff1a; Postgres 修炼之道 文章标签&#xff1a; postgresql 数据库 事务 jdbc 版权 0、概述 …

Springmvc入门案例(1)

据说&#xff0c;现在springmvc火了&#xff0c;好多企业都在使用&#xff0c;既然这样&#xff0c;咱们也得会点&#xff0c;于是乎就开始自学了&#xff0c;通过找资料&#xff0c;终于做出来了一个简单案例&#xff0c;这里分享供大家浏览&#xff0c;主要分为以下几个步骤&…

微软Project Springfield团队的F#使用心得

Project Springfield是一个用于在软件中查找关键安全错误的模糊测试服务。微软Springfield团队首席软件工程经理William Blum介绍了他们团队如何利用F#来构建云服务。 简洁性经常被认为是F#的主要优点之一。Blum提供了一些Project Springfield相关的数据&#xff1a; 为了移除一…

正则表达式中各种字符的含义

转载自 正则表达式中各种字符的含义 正则表达式(regular expression)描述了一种字符串匹配的模式&#xff0c;可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。 列目录时&#xff0c; dir *.txt或ls *.txt中的*.txt就不是一…

WRF文件打开方式

今天有幸接触了下.WRF文件&#xff0c;百度了一下&#xff1a; WRF是使用WebEx录制器生成的新格式文件&#xff0c;WebEx 设计这种格式是为了便于以后提供强大的WebEx 录制器和播放器新功能。 哦哦&#xff0c;既然是这样的话&#xff0c;那就一般的播放器肯定是不能打开&…

Java:出生日期转年龄

private int getAge(Date birthDay) {Calendar cal Calendar.getInstance();//出生日期晚于当前时间&#xff0c;无法计算if (cal.before(birthDay)) {throw new IllegalArgumentException("The birthDay is before Now.Its unbelievable!");}//当前年份int yearNow…

实现BUG自动检测 - ASP.NET Core依赖注入

我个人比较懒&#xff0c;能自动做的事绝不手动做&#xff0c;最近在用ASP.NET Core写一个项目&#xff0c;过程中会积累一些方便的工具类或框架&#xff0c;分享出来欢迎大家点评。 如果以后有时间的话&#xff0c;我打算写一个系列的【实现BUG自动检测】&#xff0c;本文将是…

java语音播报案例

在做项目的过程中&#xff0c;我们往往会用到语音播报——把文字转换成语音播放出来&#xff0c;自动识别语言进行播报&#xff0c;那么我们现在来看看怎么操作&#xff1a; 1.下载jacob.jar&#xff0c;下载地址&#xff1a;这里 2.32位操作系统下载&#xff1a;jacob-…

玩转SpringBoot之定时任务详解

玩转SpringBoot之定时任务详解 https://www.cnblogs.com/mmzs/p/10161936.html 玩转SpringBoot之定时任务详解 阅读目录&#xff1a; 序言一、静态&#xff1a;基于注解二、动态&#xff1a;基于接口三、多线程定时任务阅读正文&#xff1a; 回到顶部 序言 使用SpringBoot创…

Java开发人员必知必会的20种常用类库和API

转载自 Java开发人员必知必会的20种常用类库和API 一个有经验的Java开发人员特征之一就是善于使用已有的轮子来造车。《Effective Java》的作者Joshua Bloch曾经说过&#xff1a;“建议使用现有的API来开发&#xff0c;而不是重复造轮子”。在本文中,我将分享一些Java开发人员应…

sql server操作案例

今天没事做&#xff0c;总结了下sql server的些知识&#xff1a; --创建表 CREATE TABLE users (id INT ,name VARCHAR(50),age INT )--添加数据 SELECT * FROM users INSERT INTO users VALUES(2,张三1,13); INSERT INTO users VALUES(4,王五,12,山西省吕梁市,DEFAULT); --默…

左耳朵耗子:不灌鸡汤,说真的年龄渐长,技术人的发展之路该怎么走

技术圈中的很多人&#xff0c;最初都坚定地认为coding能改变世界。然而三五年过去后&#xff0c;还能不忘初心的人&#xff0c;少之又少。随着年龄的增长&#xff0c;梦想已被束之高阁&#xff0c;面包慢慢占据生活的大部分。对于个人发展&#xff0c;很多成功学者会给你灌各种…

集合中重写equals方法删除new的对象

COPYOverride public boolean equals(Object obj) {//1.是否为同一对象if (thisobj) {return true;}//2.判断是否为空if (objnull) {return false;}//3.判断是否是Student类型if (obj instanceof Student) {Student student(Student) obj;//4.比较属性if(this.name.equals(stud…

Java开发必须掌握的5种加密策略

转载自 Java开发必须掌握的5种加密策略 本文总结自《大型电商分布式系统实践——第四课》。文末给出获取全套PPT及视频的方式。 一、数字摘要 数字摘要也称为消息摘要,它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash函数对消息进行计算而产生。如果消息在传…

Java String格式日期加1秒(分钟或小时) java时间减一分钟,并且进行比较-时间相关的处理

https://blog.csdn.net/java0311/article/details/78047878 Java String格式日期加1秒&#xff08;分钟或小时&#xff09; chuan9966 2017-09-21 09:15:07 17101 收藏 6 文章标签&#xff1a; String格式日期加1秒 data日期加1秒 日期加1秒 版权 需求&#xff1a; 将如下…

sql server案例总结

--通过insert select 插入数据到已存在的表中 create table grade1 ( id int , name varchar(50) )insert into grade1 select * from grade select * from grade1--通过select into 语句将现有表中的数据添加到新表中&#xff0c;执行两边的话&#xff08;数据库中已存在名为…

聊下JVM内存模型

转载自 聊下JVM内存模型 1. JVM内存模型 2. 程序计数器(PC) 每个线程都会有自己私有的程序计数器(PC)。可以看作是当前线程所执行的字节码的行号指示器。 也可以理解为下一条将要执行的指令的地址或者行号。字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码…

泛型集合

作用 它是一个泛型类&#xff0c;而之前使用的时候并没有传递&#xff0c;说明java语法是允许的&#xff0c;这个时候传递的类型是Object类&#xff0c;虽然它是所有类的父类&#xff0c;可以存储任意的类型&#xff0c;但是在遍历、获取元素时需要原来的类型就要进行强制转换。…