【不安全的集合类】同步容器(如ConcurrentHashMap)、并发集合(如CopyOnWriteArrayList)

news2024/11/13 18:28:40

文章目录

    • 一、List的线程不安全
    • 二、Set的线程不安全
    • 三、Map的线程不安全

日常我们用到的集合的情况会很多,在单线程的情况下,不用考虑到线程安全的问题,但是如果在多线程开发的过程中,我们该选择哪一种类型来保证线程安全性呢

一、List的线程不安全

我们先来看一个例子:

package com.atguigu.signcenter.nosafe;

import java.util.ArrayList;
import java.util.UUID;

/**
 * 题目:请举例说明集合类是不安全的
 * @author: jd
 * @create: 2024-09-02
 */
public class NotSafeDemo {

    public static void main(String[] args) {
        ArrayList<String> StrList = new ArrayList<>();
        for (int i = 0; i <=30 ; i++) {
            new Thread(()->{
                StrList.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println("StrList = " + StrList);
            },String.valueOf(i)).start();
        }


    }

}

结果:从图中可以看出来,执行一段时间之后发生了错误;这个错误就是多线程任务中对同一个集合处理过程中出现了冲突的情况导致的
在这里插入图片描述
导致原因&解决方案
会出现ConcurrentModificationException是因为ArrayList的add方法不是线程安全的;当某个线程正在向List中写入数据时,另外一个线程同时进来写入,就会导致ConcurrentModificationException。

  1. 我们可以使用线程安全的集合类Vector,其add方法是同步方法(保证了数据一致性,但是访问性能下降);
  2. 使用Collections.synchronizedList(new ArrayList<>()) 创建一个线程安全的List (其实就是在add的时候使用了synchronized同步代码块);
  3. CopyOnWriteArrayList 写时复制ArrayList (多线程建议使用这个)
    Vector是线程安全的,能够保证数据一致性但是性能低;ArrayList牺牲了数据一致性提升了读写效率;现在想要保证数据一致性的同时也要保证读写效率,那应该怎么办?因此出现了读写分离的CopyOnWriteArrayList 。

CopyOnWriteArrayList的写时复制
我们可以先看看CopyOnWriteArrayList中add方法的源码

private transient volatile Object[] array;

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();   // 获取当前List中的所有元素
        int len = elements.length;  
        Object[] newElements = Arrays.copyOf(elements, len + 1);  // 拷贝旧元素到新的扩容的数组中
        newElements[len] = e;  // 添加新的值
        setArray(newElements);  // 更新
        return true;
    } finally {
        lock.unlock();
    }
}

CopyOnWrite容器即写时复制的容器,往一个容器中添加元素的时候,不直接往当前容器Object[]添加,而是现将当前容器Object[]进行Copy,而是复制出一个新的容器Object[] newElements向新容器添加元素,添加之后,再将原容器的引用指向新的容器setArray(newElements);这样做的好处时可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。同时添加元素的过程是通过ReentrantLock 锁来实现了同一时间内只有一个线程对此方法的访问。

二、Set的线程不安全

public class NotSafeDemo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        for (int i = 1; i <= 30; i++) {
            new Thread(() -> {
                set.add(UUID.randomUUID().toString().substring(0, 8));
                System.out.println(set);
            }, String.valueOf(i)).start();
        }
    }
}

面这段代码同样会出现java.util.ConcurrentModificationException异常;同样可以使用Collections.synchronizedSet()和CopyOnWriteArraySet,其具体原理与List的一致。这里浅说一下HashSet的源码,HashSet其实就是一个HashMap,HashSet的中存的值是HashMap的key,HashMap中的Value是一个固定对象PRESENT。

三、Map的线程不安全

同样HashMap也是线程不安全的,可以使用集合工具类Collections.synchronizedMap(new HashMap<String, String>())和ConcurrentHashMap创建线程安全的HashMap

public class NotSafeDemo {
    public static void main(String[] args) {
//        HashMap<String, String> map = new HashMap<>();
//        HashMap<String, String> map1 = (HashMap<String, String>) Collections.synchronizedMap(new HashMap<String, String>());
        ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
        for (int i = 1; i <= 30; i++) {
            new Thread(() -> {
                map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 8));
                System.out.println(map);
            }, String.valueOf(i)).start();
        }
    }
}

结果正确且正常结束
在这里插入图片描述

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

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

相关文章

【网络安全】逻辑漏洞:绕过应用程序重要功能

未经许可,不得转载。 文章目录 正文漏洞影响正文 目标:xxx.com 一个流行的汽车平台,允许用户为经销商留下评论。该平台有一个功能,用户可以点赞评论,并且它限制每个用户对每个评论只能点赞一次。 然而,我找到了绕过的方法(并不是并发)。 在点击“点赞”按钮时拦截请…

Python从0到100(五十七):机器学习-主成分分析机

主成分分析是⼀种常⽤的降维技术&#xff0c;⽤于将⾼维数据集投影到低维空间中&#xff0c;同时保留数据集的主要特征。PCA通过寻找数据中最重要的⽅向&#xff08;主成分&#xff09;&#xff0c;并将数据投影到这些⽅向上来实现降维。 1.基本原理 1、数据中心化&#xff1…

linux-squid代理服务器

squid简介 作为应用层的代理服务软件&#xff0c;Squid 主要提供缓存加速、应用层过滤控制的功能、用来缓冲Internet数据 接受来自人们需要下载的目标&#xff08;object&#xff09;的请求并适当地处理这些请求。也就是说&#xff0c;如果想下载一web页面&#xff0c;他请求…

特殊字符合集(包括各种emoji表情、windows ASCII字符、自定义字母图案等)

██████╗███████╗ ██████╗ ██╔════╝╚══███╔╝██╔═══██╗ ███████╗ ███╔╝ ██║ ██║ ╚════██║ ███╔╝ ██║▄▄ ██║ ███████║███████╗╚██████╔╝ ╚══════╝…

【小呆的热力学笔记】典型热机-燃气轮机的理想热力循环

文章目录 6.1 燃气轮机的理想热力循环6.2 燃气轮机理想热力循环热效率分析6.3 燃气轮机的理想热力循环讨论 6.1 燃气轮机的理想热力循环 燃气轮机装置主要包含三个部件&#xff1a;压气机、燃烧室和涡轮&#xff0c;详见下图示意。其中压气机主要有离心式和轴流式两种&#xf…

视频素材网站无水印的有哪些?热门视频素材网站分享!

今天我们要讨论一个让许多人都感到困扰的问题——那些高质量、无水印的视频素材到底应该在哪里寻找&#xff1f;是不是有时候感觉&#xff0c;找到合适的视频素材比找到理想的伴侣还要困难&#xff1f;不用急&#xff0c;今天我要介绍几个隐藏的宝藏网站&#xff0c;确保你在视…

ARM 异常处理(21)

异常的流程&#xff1a; 首先&#xff1a; 在硬件上阶段&#xff1a; 这里是4大步3小步 然后是 异常处理&#xff1a; 这里主要是保存现场&#xff0c;进行异常处理 然后是 异常返回&#xff1a; 主要指 恢复现场&#xff0c; 再跳转回去。 首先硬件上&#xff…

Scalefit为外骨骼辅助设备提供直观的损伤减轻测量方案

外骨骼辅助设备是有效减轻工厂中工人遭受肌肉骨骼类疾病损伤的有效工具&#xff0c;但想要更加精确直观的看到外骨骼设备能够为工人提供多少精确到数字的帮助&#xff0c;则需要专业的测量工具来实现。 Scalefit人体工程学分析软件 scalefit人体工程学分析软件让作业环境更安全…

北斗GPS车载定位终端,物流货运数智化效率助手

物流行业&#xff0c;作为国民经济的动脉&#xff0c;其效率与成本控制是企业竞争力的关键。随着科技的不断进步&#xff0c;北斗GPS车载定位终端的出现&#xff0c;正成为物流行业数智化转型的加速器&#xff0c;极大地提升了物流货运的效率与安全性。 北斗GPS车载定位终端&a…

计算机毕业设计python停车场车位推荐管理系统y4uzk

目录 博主介绍技术栈&#x1f31f;文末获取源码数据库&#x1f31f;详细视频演示具体实现截图系统设计数据库设计解决的思路python-flask核心代码部分展示可行性论证个人心得操作可行性源码获取 博主介绍 &#x1f447;&#x1f3fb; 博主介绍&#xff1a;&#x1f447;&#…

【软件测试专栏】软件测试 — 用例篇

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;软件测试专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 软件测试 — 用例篇 关键词&#xff1a;测试用例概念、测试用例的…

【基础】Three.js加载纹理贴图、加载外部gltf格式文件

1. 模型使用纹理贴图 const geometry new THREE.BoxGeometry(10, 10, 10);const textureLoader new THREE.TextureLoader(); // 创建纹理贴图加载器const texture textureLoader.load("/crate.gif"); // 加载纹理贴图const material new THREE.MeshLambertMater…

运维问题0001:MM模块-MIGO收货报错“消息号 M7036 对于采购订单********无收货可能”

1、问题解析&#xff1a; 该报错为SAP标准报错类型,针对公司不同配置/业务设计/校验逻辑&#xff0c;导致该问题原因比较多。 常见的问题总结如下&#xff1a; 1&#xff09;输入的PO信息有问题&#xff08;例如&#xff1a;PO输入错误/PO删除状态/PO冻结状态/PO已完成收货等…

HCIE认证要学多久?3个方面决定HCIE学习时长

HCIE认证作为华为公司推出的顶级专业认证&#xff0c;已经成为网络技术领域内的一个标杆。 它不仅象征着专业技能的高峰&#xff0c;也是许多IT专业人士职业发展的重要里程碑。 HCIE作为华为高级认证虽然可以不需要满足任何条件直接报考&#xff0c;但掌握必要的知识内容必不可…

MySQL复习2

高级查询 准备 create database greatselect; use greatselect;drop table if exists class; create table class (cid int(11) not null auto_increment,caption varchar(32) not null,primary key (cid) )engine innoDB AUTO_INCREMENT5 default charset utf8;create tab…

报考条件、材料、流程?关于CISP认证,你必须要了解这些

信息安全一直是一个火热的话题&#xff0c;在近两年又被推上了高峰。对此&#xff0c;相关认证也不例外。 很多朋友都想get一本安全方向的证书&#xff0c;在广大安全方向的认证中&#xff0c;CISP可谓是发展迅猛&#xff0c;并越来越广为人知&#xff0c;也越来越受到IT从业者…

python Bokeh库学习记录

First steps 2: 添加和自定义渲染器 在之前的入门指南中&#xff0c;你使用了Bokeh的figure()函数来绘制折线图。 在本节中&#xff0c;你将使用不同的渲染函数来创建各种其他类型的图表。你还将自定义你的图像外观。 渲染不同的图形符号 Bokeh的绘图界面支持多种不同的图形…

古典显示格式解一偏微分方程并绘制结果的彩色图

解如下偏微分方程 以上公式的Latex代码 \begin{cases}\frac{\partial u}{\partial t}a\frac{\partial ^2u}{\partial x^2}\,\,,0<x<1,t>0\\u\left( x,0 \right) 4x\left( 1-x \right) \,\,,0\leqslant x\leqslant 1\\u\left( 0,t \right) u\left( 1,t \right) 0 ,t\g…

补题篇--codeforces

传送门&#xff1a;Problem - G - Codeforces 题意&#xff1a; 思路&#xff1a; 注意&#xff1a; n 的范围很小&#xff0c;大概率考察状态压缩 因此这个题可以考虑用 状压dp f[i][j] 表示状态为 i 的选法&#xff0c;以第 j 首歌为结尾的播放列表中的歌曲总数 f[ i | …

生活方式对人健康影响非常大 第三篇

身体健康因素中 生活方式占到60% 赶紧去调整自己哪错了 上游的生活方式管理 是药三分毒 药物会影响身体肝肾功能,代谢 所以你要去找上游到底是我哪错了 短板越多 个健康状态越差 饮食管理是生活方式管理中难度最大的 原则1:与基因相对应相平衡 只吃素 会导致大脑萎…