线程安全的集合容器

线程安全的集合容器

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;
    	}
    
    	@Override
    	public void run() {
    		System.out.printf("订单编号为:%d的订单,完成支付,支付金额为:¥%s,支付流水号为:%s\n", orderNo, payment, trackId);
    	}
    
    	@Override
    	public 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冲突,必须竞争同一把锁(链表的头节点或红黑树的根节点)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

最新IE跳转Edge浏览器解决办法(2024.2.29)

最新IE跳转Edge浏览器解决办法&#xff08;2024.2.29&#xff09; 1.前言2. 解决方案2.1.创建快捷方式2.2.效果 3. 遗留问题 1.前言 在前几天我发布过一个关于使用卸载补丁从而解决最新的IE跳转Edge浏览器的解决方案。   但是这个方案其实存在一个BUG&#xff0c;例如我昨天重…

Mac 重新安装系统

Mac 重新安装系统 使用可引导安装器重新安装&#xff08;可用于安装非最新的 Mac OS&#xff0c;系统降级&#xff0c;需要清除所有数据&#xff09; 插入制作好的可引导安装器&#xff08;U盘或者移动固态硬盘&#xff09;&#xff0c;如何制作可引导安装器将 Mac 关机将 Ma…

本地ssh连接服务器成功,而vscode连接服务器超时

解决方案&#xff0c;按下CTRL SHIFT P 或者 COMMAND SHIFT P&#xff0c;然后输入Remote kill&#xff0c;找到以下命令Kill VS Code Server on Host...&#xff0c;然后选择连接失败的服务器进行Kill&#xff0c;之后再次尝试连接即可。 如果还不成功。找一个能登陆的方…

ubuntu基础操作(1)-个人笔记

搜狗输入法Linux官网-首页搜狗输入法for linux—支持全拼、简拼、模糊音、云输入、皮肤、中英混输https://pinyin.sogou.com/linux 1.关闭sudo密码&#xff1a; 终端&#xff08;ctrl alt t&#xff09;输入 sudo visudo 打开visudo 找到 %sudo ALL(ALL:ALL) ALL 这一行…

mount命令最新详细教程

背景 需要在设备上面&#xff0c;自动化运行u盘里面的脚本&#xff0c;并且进入一个产测模式。因此实际使用了这个mount命令&#xff0c;所以&#xff0c;写了这么一篇供大家参考。 一. 定义 mount命令在Linux和类Unix系统中用于挂载文件系统&#xff0c;即将存储设备…

PYCHARM PYSIDE6 QT 打包异常处理 no qt platform plugin could be initialized

安装有PYSIDE6的电脑 异常错误 … no qt platform plugin could be initialized … 变量名&#xff1a;QT_QPA_PLATFORM_PLUGIN_PATH &#xff08;一个字都不能改&#xff01;&#xff01;&#xff09; 自己环境变量值&#xff1a;D:\Users\topma\anaconda3\Lib\site-package…

国产航顺HK32F030M: HK32F030MJ4M6_SOP8资料

最小系统 参考资料 [1] 航顺MCU HK32F030MJ4M6-SOP8 各个文件夹简介&#xff1a; Boards&#xff1a;HK32F030xMF4P6开发板的BSP驱动代码。 Documents&#xff1a;HK32F030xMxx数据手册、用户手册、API手册以及HK32F030xMxx开发板原理图。 Package&#xff1a;HK32F030xMxx Ke…

HTML+CSS:未来属于CSS

效果演示 一个带有不同背景颜色的网格布局&#xff0c;其中一些元素可能会更大或者字体更大。 Code <main><div></div><div></div><div></div><div></div><div class"big"></div><div><…

MWC 2024丨Smart Health搭载高通Aware平台—美格发布智能健康看护解决方案,开启健康管理新体验

2月29日&#xff0c;在MWC 2024世界移动通信大会上&#xff0c;全球领先的无线通信模组及解决方案提供商——美格智能正式发布了新一代Cat.1模组SLM336Q&#xff0c;是中低速物联网应用场景的高性价比之选。本次还发布了首款搭载高通Aware™平台的智能看护解决方案MC303&#x…

Squid代理服务器配置

需求是&#xff1a;通过外网机&#xff08;跳板机&#xff09;访问内网机&#xff0c;并为内网机提供访问网络的能力。 【跳板机T】【内网机N】 公网IP&#xff1a;39.107.xx.xxx 跳板机IP&#xff1a;172.17.216.234 内网机IP&#xff1a;172.17.216.241 Squid代理服务器地址…

使用Python,maplotlib绘制树型有向层级结构图

使用Python&#xff0c;maplotlib绘制树型有向层级结构图 1. 效果图2. 源码2.1 plotTree.py绘制层级结构及不同样式2.2 plotArrow.py 支持的所有箭头样式 参考 前俩篇博客介绍了 1. 使用Python&#xff0c;networkx对卡勒德胡赛尼三部曲之《群山回唱》人物关系图谱绘制 2. 使用…

Python中reduce函数和lambda表达式的学习

reduce函数将一个数据集合&#xff08;链表&#xff0c;元组等&#xff09;中的所有数据进行下列操作&#xff1a;用传给 reduce 中的函数 function&#xff08;有两个参数&#xff09;先对集合中的第 1、2 个元素进行操作&#xff0c;得到的结果再与第三个数据用 function 函数…

基于cRIO9040 FPGA的图像处理流程

硬件准备 CompactRIO9040Basler GigE相机网线遵循GigE Vision标准的相机由高性能、多核cRIO设备支持,如cRIO-908x、cRIO-903x、cRIO-904x和cRIO-905x系列以及基于英特尔的sbRIO。 软件安装 参考:cRIO9040中NI9381模块的测试 此外,PC端需要安装VDM,VAS。 cRIO端,打开NI…

详解UDP/TCP套接字

详解UDP/TCP套接字 预备知识 理解源IP地址和目的IP地址 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址 源IP地址&#xff1a;发送主机的IP地址。目的IP地址&#xff1a;接收主机的IP地址。 认识端口号 端口号(port)是传输层协议的内容. 端口号是一个…

NVMFS5113PLWFT1G汽车级功率MOSFET 60V 10A/64A满足AEC-Q101标准

AEC-Q101认证标准详细解读&#xff1a; AEC-Q101是一种汽车电子元件可靠性标准&#xff0c;由汽车电子委员会&#xff08;Automotive Electronics Council&#xff0c;简称AEC&#xff09;制定。该标准旨在确保在汽车环境中使用的电子元件具有足够的可靠性和耐久性。 AEC-Q10…

Docker Compose实战指南:让容器管理变得简单而强大

&#x1f9e8;个人主页&#xff1a;明明跟你说过 &#x1f6a9;欢迎&#x1f397;️点赞&#x1f638;关注❤️分享 &#x1f638;希望本文能够对您有所帮助&#xff0c;如果本文有不足之处&#xff0c;或您有更好的建议、见解&#xff0c;欢迎在评论区留下您的看法&#xff0c…

力扣hot100题解(python版29-32题)

29、删除链表的倒数第N个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&a…

苍穹外卖Day03——总结3

前期文章 文章标题地址苍穹外卖Day01——总结1https://lushimeng.blog.csdn.net/article/details/135466359苍穹外卖Day01——解决总结1中存在的问题https://lushimeng.blog.csdn.net/article/details/135473412苍穹外卖Day02——总结2https://lushimeng.blog.csdn.net/articl…

Node.js中的并发和多线程处理

在Node.js中&#xff0c;处理并发和多线程是一个非常重要的话题。由于Node.js是单线程的&#xff0c;这意味着它在任何给定时间内只能执行一个任务。然而&#xff0c;Node.js的事件驱动和非阻塞I/O模型使得处理并发和多线程变得更加高效和简单。在本文中&#xff0c;我们将探讨…

gRPC知识归档

文章目录 gRPC知识归档gRPC原理什么是gRPCgRPC的特性gRPC支持语言gRPC使用场景gRPC设计的动机和原则 数据封装和数据传输问题网络传输中的内容封装和数据体积问题JSONProtobuf&#xff08;微服务之间的服务器调用&#xff0c;一般采用二进制序列化&#xff0c;比如protobuf&…