提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
我会简单的介绍一些线程安全的集合类,还有它们的基本构成,大家请不要安心难度的问题,现在只是简单的了解一下.为什么要涉及线程安全的集合类呢?因为假如说我们要在多线程环境下使用,怎么办?这里提供了俩种方案.
1.最直接的办法,使用锁,手动保证~
多个线程去修改ArrayList 此时就可能有问题就可以给修改操作进行加锁~~
2.标准库还提供了一些线程安全的版本的集合类
多线程环境使用 ArrayList
在多线程环境中,使用 ArrayList 可能会引发线程安全问题。因为 ArrayList 并不是线程安全的容器,多个线程同时修改同一个 ArrayList 实例可能会导致数据不一致或者抛出异常。
如果非要使用的话,我提供了以下解决方案
- 自己使用同步机制 (synchronized 或者 ReentrantLock)
- Collections.synchronizedList(new ArrayList);
synchronizedList 是标准库提供的一个基于 synchronized 进行线程同步的 List.
synchronizedList 的关键操作上都带有 synchronized
- 使用 CopyOnWriteArrayList
CopyOnWrite容器即写时复制的容器。
当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,
复制出一个新的容器,然后新的容器里添加元素,
添加完元素之后,再将原容器的引用指向新的容器。
这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会
添加任何元素。
所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。
优点:
在读多写少的场景下, 性能很高, 不需要加锁竞争.
缺点:
- 占用内存较多.
- 新写的数据不能被第一时间读取到.
多线程环境使用队列
在多线程环境中,使用队列是非常常见的场景,但是需要注意队列的线程安全问题。以下是几种线程安全的队列:
ConcurrentLinkedQueue:这是一个线程安全的无界队列,内部使用单向链表实现,适合于高并发场景;
LinkedBlockingQueue:这是一个线程安全的有界队列,内部使用单向链表实现,适合于固定大小的任务队列;
ArrayBlockingQueue:这是一个线程安全的有界队列,内部使用数组实现,适合于固定大小的任务队列;
PriorityBlockingQueue:这是一个线程安全的优先级队列,内部使用堆实现,适合于按优先级排序的任务队列;
SynchronousQueue:这是一个线程安全的队列,没有任何内部容量,每个插入操作必须等待一个相应的删除操作,适合于生产者和消费者交替执行的场景。
以上队列都是线程安全的,能够在多线程环境中提供高效的并发操作。需要根据实际场景选择适合的队列类型,并根据具体需求设置容量、优先级等参数。
线程环境使用哈希表
ConcurrentHashMap:这是一个线程安全的哈希表,适合于高并发场景,内部采用分段锁机制,不同的段之间可以并发操作,能够提供更好的并发性能;
Hashtable:这是一个线程安全的哈希表,内部使用 synchronized 关键字来实现线程安全,但是并发性能不如 ConcurrentHashMap;
Collections.synchronizedMap():这是一个将非线程安全的哈希表转换为线程安全的哈希表的方法,内部使用 synchronized 关键字来实现线程安全,但是并发性能不如 ConcurrentHashMap。
以上哈希表都是线程安全的,能够在多线程环境中提供高效的并发操作。需要根据实际场景选择适合的哈希表类型,并根据具体需求设置容量、并发性能等参数。
当然我推荐使用ConcurrentHashMap,为什么呢?我们来看一下
Hashtable和 ConcurrentHashMap的对比.
1.锁的粒度不同
Hashtable
ConcurrentHashMap
2.锁的优化
ConcurrentHashMap,更充分的利用了CAS机制无锁编程.
有的操作,比如获取/更新元素个数,就可以直接使用CAS完成,不必加锁了心
CAS也能保证线程安全,往往比锁更高效,但是这个东西咱们也不会特别经常使用.适用范围不像锁那么广泛
3.扩容方式不同
扩容触发条件:Hashtable 的扩容触发条件是当哈希表中元素个数大于等于阈值时,就需要进行扩容,阈值是容量 * 负载因子,负载因子默认为 0.75;ConcurrentHashMap 的扩容触发条件是当某个段的元素个数大于等于段容量的 75% 时,就需要对该段进行扩容。文章来源:https://www.toymoban.com/news/detail-411050.html
扩容策略:HashTable的扩容需要重新申请内存空间,搬运元素(把元素从旧的哈希表上删掉,插入到新的哈希表上.)如果本身元素特别多,上亿个,搬运一次,成本就很高,就会导致这一次put操作就非常卡顿
ConcurrentHashMap的扩容策略就是,化整为零,并不会试图一次性就把所有的元素都搬运过去,而是每次搬运一部分.当put触发扩容,此时就会直接创建更大的内存空间,但不会直接把所有元素搬运过去,而是搬运一小部分.文章来源地址https://www.toymoban.com/news/detail-411050.html
到了这里,关于线程安全的集合类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!