Java面试笔记:Java线程安全的集合类有哪些?线程不安全的集合类有哪些?ArrayList为什么会发生并发修改异常?

news2024/11/25 1:05:12

一、Java的集合类有哪些?

二、如何定义集合是线程不安全的?
        当多个并发同时对线程不安全的集合进行增删改的时候会破坏这些集合的数据完整性,例如:当多个线程访问同一个集合或Map时,如果有超过一个线程修改了ArrayList集合,则程序必须手动保证该集合的同步性。这就说明集合是线程不安全的。

三、实例:验证ArrayList线程不安全,抛出异常 ConcurrentModificationException 

import java.util.*;
/**
 * @author 蓝多多的小仓库
 * @title: mytest
 * @projectName test
 * @description: ldd_annotation
 * @date 2022/11/10 16:39
 */
public class mytest {
    public static void main (String[] args) {
      List<Integer> list = new ArrayList<Integer>();
      for (int i = 0; i < 10; i++) {
        final int j = i;
        new Thread(() -> {
          list.add(j);
          System.out.println(list);
        }, "" + i).start();
      }
    }
}

运行结果(结果不是唯一的,也有可能不抛出异常,你可以多运行几次): 

四、Java线程安全的集合类有哪些?

        线程安全类是确保类的内部状态以及从方法返回的值在从多个线程并发调用时是正确的类。Java线程安全的集合有Vector、HashTable、Stack、ArrayBlockingQueue、ConcurrentHashMap、ConcurrentLinkedQueue等。

        Vector:相当于 ArrayList 的翻版,是长度可变的数组,只要是关键性的操作,方法前面都加了synchronized关键字修饰,来保证线程的安全性。Vector类可以支持add(),remove(),get(),size()等方法,实例如下:

import java.util.*;
public class mytest {
    public static void main (String[] args) {
      Vector vector = new Vector();
      vector.add(2);
      vector.add(4);
      vector.add("LDD");
      vector.add(1);
      vector.add("LYD");
      System.out.println("向量: " + vector);
      vector.remove(1);
      System.out.println("移除元素后向量为: " + vector);
    }
}


        Hashtable:是一个线程安全的集合,是单线程集合,它给几乎所有public方法都加上了synchronized关键字。所以相较于Hashmap是线程安全的。

        ArrayBlockingQueue:是一个阻塞队列,底层使用数组结构实现,按照先进先出(FIFO)的原则对元素进行排序,是线程安全的。

        ConcurrentLinkedQueue:是一种FIFO的无界队列,是线程安全的,它适用于“高并发”的场景。

        ConcurrentHashMap:采用了分段锁(Segment),是一种高效但是线程安全的集合。
        Stack:栈,也是线程安全的,继承于Vector,栈后进先出。Stack类可以支持许多操作,比如push、pop、peek、search、empty等。实例:

import java.util.*;
public class mytest {
    public static void main (String[] args) {
      Stack stack = new Stack();
      stack.push(2);
      stack.push(4);
      stack.push(1);
      Integer num1 = (Integer) stack.pop();
      System.out.println("出栈元素是: " + num1);
      Integer num2 = (Integer) stack.peek();
      System.out.println("栈顶元素是: " + num2);
    }
}

        那么使用ArrayList、HashMap,需要线程安全怎么办呢?为了保证集合既是安全的而且效率高,Collections为我们提出了解决方案,把这些集合包装成线程安全的集合。使用Collections装饰的线程安全集合如下:

<T> Collection<T> synchronizedCollection(Collection<T> c); //返回指定collection 对应的线程安全的collection。
static <T> List<T> synchronizedList(List<T> list); //返回指定List对象对应的线程安全的List对象。
static <K, V> Map<K, V> synchronizedMap(Map<K, V> m); //返回指定Map对象对应的线程安全的Map对象。
static <T> Set<T> synchronizedSet(Set<T> s); //返回指定Set对象对应的线程安全的Set对象。
static <K, V> SortedMap<K, V> synchronizedSortedMap(SortedMap<K, V> m); //返回指定SortedMap对象对应的线程安全的SortedMap对象。

        java.util.concurrent.*下的线程安全集合类:如:CopyOnWriteArrayList、 CopyOnWriteArraySet等,它们里面包含三类关键词: Blocking、CopyOnWrite、Concurrent Blocking,大部分实现基于锁,并提供用来阻塞的方法。

        关于CopyOnWriteArrayList是怎么保证线程安全的?请参考上一篇文章:Java面试笔记:CopyOnWriteArrayList是怎么保证线程安全的?_蓝多多的小仓库的博客-CSDN博客

五、线程不安全的集合类有哪些?

        Hashmap:HashMap在put操作的时候,如果插入的元素超过了容量(由负载因子决定)的范围就会触发扩容操作,就是resize,这个会重新将原数组的内容重新hash到新的扩容数组中,在多线程的环境下,存在同时其他的元素也在进行put操作,如果hash值相同,可能出现同时在同一数组下用链表表示,造成闭环,导致在get时会出现死循环,所以HashMap是线程不安全的。

        ArrayList: List 对象在做 add 时,执行 Arrays.copyOf 的时候,返回一个新的数组对象。当有线程 A、B… 同时进入 grow方法,多个线程都会执行 Arrays.copyOf 方法,返回多个不同的 elementData 对象,假如,A先返回,B 后返回,那么 List.elementData ==A. elementData,如果同时B也返回,那么 List.elementData ==B. elementData,所以线程B就把线程A的数据给覆盖了,导致线程A的数据被丢失。也可以参考上面提供的实例验证ArrayList线程不安全,抛出异常 ConcurrentModificationException 来理解ArrayList为什么是不安全的。

        LinkedList:与Arraylist线程安全问题相似,线程安全问题是由多个线程同时写或同时读写同一个资源造成的。

        HashSet:底层数据存储结构采用了Hashmap,所以Hashmap会产生的线程安全问题HashSet也会产生。
        TreeSet、TreeMap等

六、ArrayList为什么会发生并发修改异常?那么如何避免ArrayList的并发问题?

        ArrayList是线程不安全的,在多线程并发访问的时候可能会出现问题,会存在线程B把线程A的数据给覆盖了,导致线程A的数据被丢失的情况,也有可能在扩容时有数组索引越界的异常产生。解决方案:

(1)使用Collections.synchronizedList()方法对ArrayList对象进行包装

ArrayList<Integer> arraylist = Collections.synchronizedList(new ArrayList());

(2)使用并发容器CopyOnWriteArrayList

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();

        详情请参考:ArrayList为什么会出现并发问题以及相应的解决办法_Max的外企搬砖随笔的博客-CSDN博客

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

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

相关文章

3A企业认定有哪些好处?

企业参与申报和认证有什么益处&#xff1f;这个问题可能应该是广大企业参与前最为关心的问题之一了 1、可快速有效提升企业资质、获得国家政府的认可&#xff1b;并将获得由商务部颁发的具有统一编号的牌匾和证书。 2、是企业履约能力、投标信誉、综合实力与竞争力的体现&…

数学建模--优化类模型

目录 一、根据目标函数约束条件类型分类 1、线性规划 ①线性规划模型的一般形式 ​②用MATLAB优化工具箱解线性规划 ③模型分析 2、非线性规划 ①非线性规划的基本概念 ②非线性规划的基本解法 ③二次规划 ④一般非线性规划 二、控制变量类型分类 1、整数规划 …

总结线程安全问题的原因和解决方案

一. 线程安全问题 概念 首先, 线程安全的意思就是在多线程各种随机调度的情况下, 代码不出现 bug 的情况. 如果在多线程调度的情况下, 出现 bug, 那么就是线程不安全. 二. 观察线程不安全的情况 下面我们用多线程来累加一个数, 观察线程不安全的情况: 用两个线程, 每个线程…

树--堆和优先权队列

数据结构中的堆和栈与操作系统内存划分中的堆和栈没有关系 一、堆的定义 一个大小为n的堆是一棵包含n个结点的完全二叉树&#xff0c;其根节点称为堆顶。 根据堆中亲子结点的大小关系&#xff0c;分为大堆和小堆&#xff1a; &#xff08;1&#xff09;最小堆&#xff1a;树中…

高斯原型网络原论文高质量翻译

论文地址&#xff1a;Gaussian Prototypical Networks for Few-Shot Learning on Omniglot 文章目录摘要1 引言1.1 Few-shot learning1.2 高斯原型网络2 相关工作3 方法3.1 编码器3.2 偶发性训练3.3 定义一个类3.4 评估模型4 数据集5 实验5.1 协方差估计的用法6 结论摘要 我们…

万字长文解读计算机视觉中的注意力机制(附论文和代码链接)

文中论文和代码已经整理&#xff0c;如果需要&#xff0c;点击下方公众号关注&#xff0c;领取&#xff0c;持续传达瓜货 所向披靡的张大刀 注意力机制是机器学习中嵌入的一个网络结构&#xff0c;主要用来学习输入数据对输出数据贡献&#xff1b;注意力机制在NLP和CV中均有使…

目标检测算法——YOLOv5/YOLOv7改进之结合无参注意力SimAM

目录 &#xff08;一&#xff09;前言介绍 1.摘要 2.不同注意力步骤比较 &#xff08;二&#xff09;相关实验 &#xff08;三&#xff09;YOLOv5结合无参注意力SimAM 1.配置.yaml文件 2.配置common.py 3.修改yolo.py SimAM&#xff1a;无参数Attention助力分类/检测/分…

点云应用——三维空间边界点排序+机器人轨迹引导(1)

三维空间边界点排序机器人轨迹引导一、前言二、思路一&#xff1a;利用重建思路三、思路二&#xff1a;利用PCL边界提取方法三维空间点排序四、后续一、前言 最近做了点云边界提取、并实时发送至机器人进行引导的研究&#xff0c;主要遇到了两个问题&#xff1a; 1&#xff09;…

Python画爱心——一颗会跳动的爱心~

节日就快到来了&#xff0c;给你的Ta一个惊喜吧~ 今天给大家分享一个浪漫小技巧&#xff0c;利用Python制作一个立体会动的心动小爱心 成千上百个爱心汇成一个大爱心&#xff0c;从里到外形成一个立体状&#xff0c;给人视觉上的冲击感&#xff01;浪漫极了↓ 微信扫码添加&a…

CUDA 从入门到放弃(一)

CUDA从入门到放弃系列包含内容 异构并行计算CUDA编程模型CUDA执行模型CUDA内存CUDA流和并发CUDA指令级原语GPU加速库多GPU编程 本文你将了解到 异构并行计算CUDA编程模型 温馨提示: 本文可能引发C/C零基础的读者不适,请谨慎观看. 一、聊聊异构并行计算 异构并行计算的本质是…

MQTT Broker mosquito配置以及使用tls证书登录附上Python调用代码

MQTT Broker mosquito配置以及使用tls证书登录 文章目录MQTT Broker mosquito配置以及使用tls证书登录1. 前言2. 安装3. mosquito相关命令3.1 运行停止查看状态3.2 创建可以登录mosquito的用户3.3 配置权限规则文件3.4 配置mosquito3.5 使用mosquito_pub和mosquito_sub测试3.5.…

web手势库Alloyfinger

前言 在上一篇文章 前端pdf预览、pdfjs的使用&#xff0c;我们使用pdf.js 来实现了pdf的预览。但是客户车间里的电脑是触摸屏&#xff0c;要求能够手势放大图纸&#xff0c;能够拖动图纸。最终决定使用 Alloyfinger 来解决手势的问题。 官方github https://github.com/Alloy…

计算机网络(一):计算机网络概念、功能、组成

计算机网络的概念 计算机网络&#xff1a;是一个将分散的、具有独立功能的计算机系统&#xff0c;通过通信设备与线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统 计算机网络是互连的、自治的计算机集合。 互连&#xff1a;互联互通 自治&#xff1a;无…

前端面经 前端优化

前端面经 前端优化 文章目录前端面经 前端优化HTTP/2 Web优化最佳实践DNS与解析如何使用CDN分发缓存策略页面渲染优化避免CSS、JS阻塞CSS阻塞JS的阻塞改变JS阻塞的方式使用字体图标iconfont代替图片图标降低CSS选择器的复杂性减少重绘和回流如何避免图片资源优化Webpack优化降低…

【Vue】VueCLI 的使用和单文件组件(1)

学习内容&#xff1a; 1&#xff09;了解一下 Vue 的脚手架工具&#xff1b; 2) 认识一下 Vue 里面的单文件组件。‍‍ 在真正开发大型项目的时候&#xff0c;实际上我们并不能通过一个这样的index点html的方式去编写一个比较大型的项目&#xff0c;‍‍ 所以我们要学习使用 V…

JavaScript 69 JavaScript Web API 69.3 Web History API

JavaScript 文章目录JavaScript69 JavaScript Web API69.3 Web History API69.3.1 History back() 方法69.3.2 History go() 方法69.3.3 History 对象属性69.3.4 History 对象方法69 JavaScript Web API 69.3 Web History API Web History API 提供了访问 windows.history 对…

Linux进程与操作系统详解

文章目录一&#xff1a;冯诺依曼体系二&#xff1a;操作系统三&#xff1a;进程和PCB四&#xff1a;进程相关的指令五&#xff1a;getpid和getppid系统调用六&#xff1a;fork系统调用七&#xff1a;进程状态八&#xff1a;Linux下进程状态大全8.1&#xff1a;R(running)8.2&am…

Hive3 - HiveSQL 特征及操作

一、HiveSQL特征 Hive SQL&#xff08;HQL&#xff09;与SQL的语法大同小异&#xff0c;基本上是相通的&#xff0c;对SQL掌握的可以非常快的上手使用Hive SQL。不过在一些细节上需要特别注意Hive自己特有的语法知识点&#xff0c;下面分别进行介绍。 1. 字段数据类型 Hive数…

【附源码】Python计算机毕业设计烹饪课程预约系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

电脑重装系统c盘如何备份资料

现在越来越多的用户都喜欢重装自己所喜欢的电脑系统&#xff0c;但需要在重新安装系统之前备份自己的电脑。因此有很多用户问重装系统c盘如何备份的文件。今天小编就教下大家重装系统c盘如何备份的教程。 工具/原料&#xff1a; 系统版本&#xff1a;windows7系统 品牌型号&…