线程安全的集合容器

线程安全的集合容器

List集合中的线程安全的集合容器:

在旧版本中Vector是线程安全的集合容器,在JDK 1.5以后CopyOnWriteArrayList也是线程安全的集合容器,CopyOnWriteArrayList的数据结构是Object类型的数组。

CopyOnWriteArrayList是如何实现线程安全的:通过 “ReentrantLock锁” 实现线程安全,写入操作(添加、删除、修改元素)使用同一个Lock对象进行线程安全的同步管理,采用COW思想(CopyOnWrite);因为CopyOnWriteArrayList集合在扩容时实在原数组基础上加一进行扩容,就是添加一个元素扩容一下,当它进行扩容时,会将原数组进行复制到一个新数组中进行添加元素的操作,所以不会影响集合的读取;读写分离:线程读取集合元素的同时,其它线程可以同时写入

Set集合中的线程安全的集合容器:

CopyOnWriteArraySet: CopyOnWriteArraySet的底层就是CopyOnWriteArrayList,但在此基础上添加了去重方法

Queue(队列):

队列的特点:FIFO先进先出

BlockingQueue阻塞队列:

特点:在队列的基础上,使用两个不同的线程进行队列操作

在这里插入图片描述

  • 读取线程负责读取队列元素,进行出队操作,当队列为空时,读取线程阻塞;发生出队操作后,唤醒阻塞中的写入线程;
  • 写入线程负责写入队列元素,进行入队操作,当队列为满时,写入线程阻塞;发生入队操作后,唤醒阻塞中的读取线程;
实现类
  • 有界队列:ArrayBlockingQueue

    数据结构:Object类型的数组

    因为ArrayBlockingQueue是有Object数组实现的并且在ArrayBlockingQueue只有有参构造方法,参数是队列的大小

    线程的同步:通过一个ReentrantLock锁实现(写入的同时,不允许读取)
    在这里插入图片描述
    通过观察源码可以得知:在ArrayBlockingQueue的put()方法中,当队列的元素个数等于数组长度会使put线程进入阻塞状态(并不是真正意义上的阻塞相当于等待状态)

    小案例:

    package Threadday4;import java.util.concurrent.ArrayBlockingQueue;public class Test04 {public static void main(String[] args) throws InterruptedException {// 基于Object数组实现的有界阻塞队列ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<String>(5);for (int i = 1; i <= 100; i++) {//入队操作可以使用put方法
    //			arrayBlockingQueue.offer("A" + i);arrayBlockingQueue.put("S" + i);if (i % 5 == 0) {//出队操作可以使用take方法
    //				System.out.println("出队元素:"+arrayBlockingQueue.poll());System.out.println("出队元素:"+arrayBlockingQueue.take());}System.out.println(arrayBlockingQueue);}}
    }
  • 无界队列:LinkedBlockingQueue

    数据结构:单向链表

    无界队列的无界只是相对意义上的无界

    线程同步:通过两个ReentrantLock锁实现(写入操作使用putLock,读取操作使用takeLock)

    在这里插入图片描述

    小案例:

    package Threadday4;import java.util.concurrent.LinkedBlockingQueue;public class Test05 {public static <E> void main(String[] args) throws InterruptedException {// 基于单项列表实现的无届队列(无界)// 它的线程同步是通过两个ReentrantLock锁实现的LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();for (int i = 1; i <= 100; i++) {//入队操作可以使用put方法queue.put("S" + i);if (i % 5 == 0) {//出队操作可以使用take方法System.out.println("出队元素:"+queue.take());}System.out.println(queue);}}
    }
  • 延迟队列:DelayedWorkQueue

    队列中的元素按照延迟时间排序

  • 优先队列:PriorityBlockingQueue

    队列中的元素按照指定的优先级排序

    小案例:使用一个简单的订单说明

    OrederPayMent类

    package Threadday4;import java.math.BigDecimal;
    import java.util.UUID;public class OrederPayMent implements Runnable ,Comparable<OrederPayMent>{private int orderNo; // 订单编号private String trackId; // 支付流水号private BigDecimal payment; // 支付金额public OrederPayMent(int orderNo,  BigDecimal payment) {trackId = UUID.randomUUID().toString().substring(0, 10) + System.currentTimeMillis();this.orderNo = orderNo;this.payment = payment;}public int getOrderNo() {return orderNo;}public void setOrderNo(int orderNo) {this.orderNo = orderNo;}public String getTrackId() {return trackId;}public void setTrackId(String trackId) {this.trackId = trackId;}public BigDecimal getPayment() {return payment;}public void setPayment(BigDecimal payment) {this.payment = payment;}@Overridepublic void run() {System.out.printf("订单编号为:%d的订单,完成支付,支付金额为:¥%s,支付流水号为:%s\n", orderNo, payment, trackId);}@Overridepublic int compareTo(OrederPayMent o) {return o.payment.compareTo(this.payment);}}

    根据自定义的优先级规则(价钱)实现Comparable接口

    package Threadday4;import java.math.BigDecimal;
    import java.util.concurrent.PriorityBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;public class Test06 {public static void main(String[] args) {//创建线程池ThreadPoolExecutor pool = new ThreadPoolExecutor(0, 2, 0, TimeUnit.SECONDS, new PriorityBlockingQueue<Runnable>());for(int i = 0; i<=100;i++) {pool.execute(new OrederPayMent(i, new BigDecimal(String.valueOf(Math.random()*100))));}}
    }
Map集合中线程安全的集合容器:

Hashtable:数据结构:数组加链表因为hashtable的方法中是为synchronized关键字锁修饰的所有线程安全但是性能差

ConcurrentHashMap

数据结构:Node[ ]数组 + 链表 + 红黑树

在JDK1.7版本中,ConcurrentHashMap是通过分段锁来实现线程安全的,分段锁:是将数组划分成若干不同的"区域",每个区域使用一把锁来控制线程安全;在JDK1.8版本以后,ConcurrentHashMap是通过synchronized同步锁 + CAS来实现线程安全的,就是在多线程并发时,产生Hash冲突,必须竞争同一把锁(链表的头节点或红黑树的根节点)

]数组 + 链表 + 红黑树

在JDK1.7版本中,ConcurrentHashMap是通过分段锁来实现线程安全的,分段锁:是将数组划分成若干不同的"区域",每个区域使用一把锁来控制线程安全;在JDK1.8版本以后,ConcurrentHashMap是通过synchronized同步锁 + CAS来实现线程安全的,就是在多线程并发时,产生Hash冲突,必须竞争同一把锁(链表的头节点或红黑树的根节点)

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于JAVA的毕业设计分配选题系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 专业档案模块2.2 学生选题模块2.3 教师放题模块2.4 选题审核模块 三、系统展示四、核心代码4.1 查询专业4.2 新增专业4.3 选择课题4.4 取消选择课题4.5 审核课题 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpri…

事物管理(黑马学习笔记)

事物回顾 在数据库阶段我们已学习过事务了&#xff0c;我们讲到&#xff1a; 事物是一组操作的集合&#xff0c;它是一个不可分割的工作单位。事务会把所有的操作作为一个整体&#xff0c;一起向数据库提交或者是撤销操作请求。所以这组操作要么同时成功&#xff0c;要么同时…

SZTU抢课脚本python

声明:这篇代码是我基于我向我的部长学习的&#xff0c;带有一些理解和稍微一丢丢的改善&#xff0c;就是把他的一些模块套入到循环里这样可以一次性枪很多课&#xff0c;不过写的不是并发的所以会有顺序导致的无法同时抢很多课&#xff0c;而是抢完一个又一个 在这里也附上大佬…

android开发书籍推荐,android面试复习

笼统来说&#xff0c;中年程序员容易被淘汰的原因其实不外乎三点。 1、输出能力已到顶点。这个人奋斗十来年了&#xff0c;依旧碌碌无为&#xff0c;很明显这人的天花板就这样了&#xff0c;说白了&#xff0c;天赋就这样。 2、适应能力越来越差。年纪大&#xff0c;有家庭&…

qt5.15 升级 qt 6.5 部分问题 解决修复

报错 QT5_USE_MODULES 升级 QT6_ADD_RESOURCES qt_add_resources Compiles binary resources into source code. CMake Commands in Qt6 Core | Qt Core 6.6.2

HCIA-Datacom实验指导手册:6 构建基础 WLAN 网络

HCIA-Datacom实验指导手册&#xff1a;6 构建基础 WLAN 网络 一、实验介绍&#xff1a;二、实验拓扑&#xff1a;三、实验目的&#xff1a;四、配置步骤&#xff1a;1.掌握ap上线的配置方式和上线过程。ac配置验证 步骤 2 掌握隧道模式和旁挂模式下ac的配置。步骤 3 掌握查看ap…

4、正则表达式、本地存储

一、正则表达式 1、定义 用事先定义好的一些特定字符&#xff0c;这样的字符组合&#xff0c;组合成一个“规则字符串” 2、正则的组成 特殊字符 字母、数字、下划线、中文、特殊字符… 元字符&#xff08;常用&#xff09; 1、\d 匹配至少有一个数字 var reg /\d/ /…

【ElfBoard】基于 Linux 的智能家居小项目

大家好&#xff0c;我是 Hello阿尔法&#xff0c;这段时间参与了保定飞凌嵌入式技术有限公司举办的 ElfBoard 共创社招募活动&#xff0c;并有幸成为了一名共创官&#xff0c;官方寄来了一块 ELF 1 开发板&#xff0c;开箱看这里 ELF 1 开箱初体验。 作为共创官&#xff0c;我…

视频转字幕文字的方法有哪些?这些方法轻松搞定

怎么样通过视频链接将文字转化出来&#xff1f;当我们刷到一个喜欢的视频文案&#xff0c;想要复制出来已做借鉴&#xff0c;这个时候就需要用到一些神奇的AI工具。随着人工智能技术的不断发展&#xff0c;视频链接转文字已经变得越来越容易。现在市面上有很多在线工具可以将视…

任务创建和调度器开启

目录 一、任务创建 二、静态任务和动态任务创建的区别 三、任务调度 1、vTaskStartScheduler()调度器&#xff1a; 2、内核相关硬件初始化函数分析&#xff1a;xPortStartScheduler() 3、启动第一个任务函数分析&#xff1a;prvStartFirstTask() 4、SVC中断服务函数 5、…

优思学院|质量工程师需要学习什么软件?

初入职质量工程师的朋友常常会问&#xff1a;质量工程师需要学习什么软件&#xff1f;在质量控制和管理的世界里&#xff0c;拥有强大的数据分析工具是走向成功的关键&#xff0c;因此&#xff0c;对于质量工程师来说&#xff0c;掌握正确的软件不仅能提升工作效率&#xff0c;…

NebulaGraph基础(默认看了入门篇)

感谢阅读 官方链接运算符比较运算符布尔符管道符集合运算符UNION、UNION DISTINCT、UNION ALL官方示例代码&#xff08;并集&#xff09;INTERSECT官方示例代码&#xff08;交集&#xff09;MINUS 字符串运算符官方代码&#xff08;字符串&#xff09; 列表运算符算术运算符 Ne…