集合类多线程(JUC)

一、集合框架概述

集合: 是广义上的集合,简单理解就是容器。注意:集合只能存放对象类型的数据。
集合框架: 指的是 java.util 包中定义的各种容器类、相关的工具类、接口的统称。不同的容器存储不同结
构的数据。使用时要进行导包操作
百度网盘 获取JDKAPI文档,学习集合基础
链接:https://pan.baidu.com/s/1Z5mL0vVbXX1mMS8UqRaa6Q
提取码:2ktk
集合框架图

二、集合分类

集合一共分为两大类(3小类):

Collection-----即集合 它是像数组一样的单值容器,容器的容量可以动态变化(数组的容量是固定的)。
List-----列表,可以简单理解为有序数组。
Set-----集合,类似于数学中的集合,容器中不允许出现重复元素。
Map-----即映射(或字典) 它是键值对容器,容量可以动态变化。

三、并发集合类

1.List(有序、允许重复元素)

特点:
1.有序性: 列表中的元素按照它们被添加的顺序排列,并且可以根据它们的索引位置来访问。
2.可重复性: 列表允许包含重复的元素,即同一个元素可以出现多次。
3.可变性: 一些列表实现是可变的,意味着可以添加、删除或修改列表中的元素;而另一些列表实现是不可变的,意味着一旦创建就无法更改。

/**
	* 利用ArrayList在多线程下面跑会出现: java.util.ConcurrentModificationException(并发修改异常)
	* 解决方案:
	* 1. List<String> stringList = new Vector<>();Vector线程安全的不会出现并发修改异常,主要是在add方法加了synchronized,会降低速度不推荐;
	* 2. List<String> stringList = Collections.synchronizedList(new ArrayList<>());
	* 3. JUC List<String> stringList = new CopyOnWriteArrayList<>();
*/
//CopyOnWrite 写入时复制,执行操作时创建一个底层数组的副本,并在副本上进行修改,而不是直接在原数组上进行修改
//每次修改操作都需要创建一个新的副本,因此 CopyOnWriteArrayList 的修改操作会比较耗费内存和时间。但是在读取操作(获取元素、遍历等)方面,由于不涉及到修改操作,所以读取操作是无锁的且非常高效的。
List<String> stringList = new CopyOnWriteArrayList<>();
for (int i=0; i<15;i++){
   new Thread(()->{
       stringList.add(UUID.randomUUID().toString().substring(1,6));

       System.out.println(Thread.currentThread().getName() + "---" + stringList);
   },String.valueOf(i)).start();
}

2.Set(无序、不允许重复元素)

特点:
1.无序性: 集合中的元素没有特定的顺序,即它们不会按照特定的顺序排列。
2.不允许重复元素: 集合中不会包含重复的元素,即同一个元素只会出现一次。
3.可变性: 一些集合实现是可变的,允许添加、删除或修改集合中的元素;而另一些集合实现是不可变的,一旦创建就无法更改。
底层采用的是map,所以数据唯一且无序。
在这里插入图片描述

/**
	* Set<String> stringList = new HashSet<>();
	* 同理可证:利用HashSet在多线程下面跑会出现: java.util.ConcurrentModificationException(并发修改异常)
	* 解决方案:
	* 1.Set<String> stringList = Collections.synchronizedSet(new HashSet<>());
	* 2.Set<String> stringList = new CopyOnWriteArraySet<>();
*/
//CopyOnWriteArraySet在添加、修改和删除元素时,并不直接在原始数组上进行操作,而是先将原始数组进行复制,然后在副本上进行修改操作。这样做的好处是,在修改过程中,原始数组不会被其他线程影响到,从而保证了线程安全性。
//由于CopyOnWriteArraySet在修改操作时需要进行数组复制,因此会占用较多的内存。因此,它适用于存储元素数量较少且读取操作频繁的场景,而不适用于存储大量元素或需要频繁进行修改操作的场景。
Set<String> stringList = new CopyOnWriteArraySet<>();
for (int i=0; i<15;i++){
   new Thread(()->{
       stringList.add(UUID.randomUUID().toString().substring(1,6));
       System.out.println(Thread.currentThread().getName() + "---" + stringList);
   },String.valueOf(i)).start();
}

3.Map(键值对(Key-Value)映射关系)

特点:
1.键的唯一性: 在Map中,每个键都是唯一的,不允许重复。
2.键值对的映射关系: 每个键都与一个值相关联,即键值对之间存在一一对应的映射关系。
3.无序性(部分实现): 在某些Map实现中,键值对的存储顺序是不固定的,即Map中的元素不会按照特定的顺序排列。而在另一些实现中,可能会维护一定的顺序,例如按照键的排序顺序
加载因子(Load Factor): 加载因子是指当哈希表中的条目数量达到总容量的多少比例时,触发哈希表的重新哈希(rehashing)操作。在 Java 中,通常情况下,加载因子的默认值为 0.75。这意味着当哈希表中的元素数量达到容量的 75% 时,哈希表会自动扩容并重新哈希,以保持哈希表的性能。
初始化容量(Initial Capacity): 初始化容量是指在创建哈希表时,最初分配的数组大小。在 Java 中,哈希表的默认初始容量为 16。如果你知道将要存储的元素数量的大致范围,可以通过指定初始容量来避免多次重新哈希,从而提高性能

/**
	* Map<String,Object> mapList = new HashMap<>();
	* 同理可证:利用mapList在多线程下面跑会出现: java.util.ConcurrentModificationException(并发修改异常)
	* 解决方案:
	* 1.Map<String,Object> mapList = Collections.synchronizedMap(new HashMap<>());
	* 2.Map<String,Object> mapList = new ConcurrentHashMap<>();
*/
Map<String,Object> mapList = new ConcurrentHashMap<>();
for (int i=0; i<15;i++){
   new Thread(()->{
       mapList.put(UUID.randomUUID().toString().substring(1,6),UUID.randomUUID().toString().substring(1,6));
       System.out.println(Thread.currentThread().getName() + "---" + mapList);
   },String.valueOf(i)).start();
}
ConcurrentHashMap特点

1.线程安全性: ConcurrentHashMap是线程安全的,多个线程可以同时读取和修改ConcurrentHashMap而不需要额外的同步措施。
2.分段锁机制: ConcurrentHashMap内部采用了分段锁(Segment)的机制,将整个Map分成多个段(Segment),每个段相当于一个小的哈希表,不同的段可以由不同的线程同时操作,从而减小了锁的粒度,提高了并发性能。
3.可调整的并发级别: ConcurrentHashMap允许在创建时指定并发级别,即期望被多少线程同时访问。并发级别决定了ConcurrentHashMap内部分段的数量,从而影响了并发操作的效率。
4.支持高效的并发读取和修改: ConcurrentHashMap在进行读取操作时,不会阻塞其他读取操作;而在进行修改操作时,只会对涉及到的段加锁,而不会锁定整个Map,从而提高了并发读取和修改的效率。
5.不允许null键和null值: ConcurrentHashMap不允许存储null键和null值,如果尝试存储null键或null值,将会抛出NullPointerException。

  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值