【JUC】三、集合的线程安全

news/2024/5/20 6:51:01 标签: 线程安全, JUC, 写时复制

文章目录

  • 1、ArrayList集合线程安全问题分析
  • 2、解决方式一:Vector或synchronizedList( )
  • 3、解决方式二:CopyOnWriteArrayList 写时复制
  • 4、HashSet集合线程不安全的分析与解决
  • 5、HashMap集合线程不安全的分析与解决

1、ArrayList集合线程安全问题分析

对List集合非线程安全的Demo代码:

public class ArrayListDemo {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        //多个线程同时写入List集合
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                //加元素
                list.add(UUID.randomUUID().toString().substring(0,8));
                //遍历输出集合
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

运行:

在这里插入图片描述

ConcurrentModificationException异常,是在多线程环境下,当一个线程正在遍历集合,而另一个线程对集合进行了修改操作时,就会抛出这个异常。以ArrayList为例,其add方法源码,未加synchronized关键字:

在这里插入图片描述

再点击报错详情,进入抛出异常的方法:

在这里插入图片描述

modCount即集合新增的次数,是实际修改次数,而expectedModCount是预期修改次数,它是ArrayList的一个内部类Itr的成员变量,调用iterator()获取迭代器时,内部创建Itr对象,此时,modCount会赋值给expectedModCount:

在这里插入图片描述

拿到迭代器对象,要遍历集合时,modCount已经赋值给expectedModCount,而此时其他线程继续add,modCount+1,modCount和expectedModCount就不相等了。

2、解决方式一:Vector或synchronizedList( )

List接口的另一个实现类Vector,其add方法加了关键字,使用它可解决线程安全问题,但很古老了,since1.2,很少用了。

在这里插入图片描述

List<String> list = new Vector<>();
//重复代码略

同样一种古老的解决方案,可以用Collections的synchronizedList方法,传入一个有线程安全问题的List,如ArrayList:

List<String> list = Collections.synchronizedList(new ArrayList<>());

3、解决方式二:CopyOnWriteArrayList 写时复制

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

完整demo:

public class ArrayListDemo {

    public static void main(String[] args) {
        List<String> list = new CopyOnWriteArrayList<>();
        //多个线程同时写入List集合
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                //加元素
                list.add(UUID.randomUUID().toString().substring(0,8));
                //遍历输出集合
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

原理是写时复制技术,即:

  • 对这个List实现类的集合,可以多线程并发读
  • 往集合中写的时候,则只能独立写,先复制一份原来的集合,这个时候读还是读原来的,然后往新集合里面写入新的内容
  • 写完后新旧合并,再读时,就读这个合并后的集合

在这里插入图片描述
看下源码,再对照着理解写时复制

在这里插入图片描述

4、HashSet集合线程不安全的分析与解决

public class HashSetDemo {

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

运行:

在这里插入图片描述

解决办法类比上面的List,使用CopyOnWriteArraySet

Set<String> set = new CopyOnWriteArraySet<>();

5、HashMap集合线程不安全的分析与解决

public class HashSetDemo {

    public static void main(String[] args) {
        Map<String,string> map = new HashMap<>();
        for (int i = 0; i < 30; i++) {
        	String key = String.valueOf(i);
            new Thread(() -> {
                //写入
                map.put(key,UUID.randomUUID().toString().substring(0,8));
                //读
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }
}

在这里插入图片描述
解决办法类比List,用ConcurrentHashMap

Map<String,String> map = new ConcurrentHashMap<>();

http://www.niftyadmin.cn/n/5176636.html

相关文章

python用pychart库,实现将经纬度信息在地图上显示

python使用pyecharts对给到的经纬度数据进行位置标注&#xff0c;下面是批量更新。给入数据&#xff0c;将地图生成。实验数据在下面附件。 from pyecharts import options as opts from pyecharts.charts import Geo import osfolder_path F:\\GPS file_names os.listdir(f…

解决pikachu中RCE中文乱码的问题

这个问题我在DVWA中的RCE栏目同样遇到过&#xff0c;今天在做pikachu的RCE的时候也遇到了&#xff0c;所以特此来解决一下这个问题&#xff0c;解决方法很简单&#xff0c;在源码中加入下一行代码。 $result iconv("GBK", "UTF-8", $result);加在68行前面…

电商平台api接口,淘宝/天猫、1688、拼多多、亚马逊等电商数据平台api接口演示案例

API简单来说是一种数据的传输方式&#xff0c;使用已经开发好的API接口可以缩短项目时间&#xff0c;减少开发成本。 比如说数据宝平台提供的实名认证API接口&#xff0c;像这种实名认证类的API接口是无法自行开发的&#xff0c;如果自行对接部委&#xff0c;能否成功不说&…

pandas读写json的知识点

pandas对象可以直接转换为json&#xff0c;使用to_json即可。里面的orient参数很重要&#xff0c;可选值为columns,index,records,values,split,table A B C x 1 4 7 y 2 5 8 z 3 6 9 In [236]: dfjo.to_json(orient"columns") Out[236]: {"A":{"x&qu…

OpenAI DALL·E 3文生图模型技术揭秘(建议收藏)

欢迎来到魔法宝库&#xff0c;传递AIGC的前沿知识&#xff0c;做有格调的分享❗ 喜欢的话记得点个关注吧&#xff01; DALLE 3是OpenAI发布的一款文生成图AI系统&#xff0c;它无缝接入ChatGPT&#xff0c;通过接受文本提示作为输入&#xff0c;生成相应的图像作为输出。先来看…

监控和数据采集软件架构和详细设计

介绍 监控和数据采集软件通过提供实时监控、数据收集和分析功能&#xff0c;在各个行业中发挥着至关重要的作用。这些软件应用程序可帮助企业收集有价值的见解、优化流程并做出明智的决策。在本文中&#xff0c;我们将探讨监测和数据采集软件的软件架构、编程技术和详细设计规范…

数据分类分级方法及典型应用场景

1 2021-09-29 来源&#xff1a;数据学堂 [打印本稿][字号 大 中小] 《数据安全法》的第二十一条明确规定了由国家建立数据分类分级保护制度&#xff0c;根据数据在经济社会发展中的重要程度&#xff0c;以及一旦遭到篡改、破坏、泄露或者非法获取、非法利用&#xff0c;对国…

数据结构上机实验——图的实现(以无向邻接表为例)、图的深度优先搜索(DFS)、图的广度优先搜索(BFS)

文章目录 数据结构上机实验1.要求2.图的实现&#xff08;以无向邻接表为例&#xff09;2.1创建图2.1.1定义图的顶点、边及类定义2.1.2创建无向图和查找2.1.3插入边2.1.4打印函数 2.2图的深度优先搜索&#xff08;DFS&#xff09;2.3图的广度优先搜索&#xff08;BFS&#xff09…