小工具知识网

当前位置: 首页 > 行业知识 > 线程安全的集合容器

行业知识

线程安全的集合容器

2026-10-23 14:28:09 来源:互联网转载

线程安全的集合容器

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 arrayBlockingQueue = new ArrayBlockingQueue(5);for (int i = 1; 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);}}}public static // 基于单项列表实现的无届队列(无界)// 它的线程同步是通过两个ReentrantLock锁实现的LinkedBlockingQueue//入队操作可以使用put方法queue.put("S" + i);if (i % 5 == 0) {//出队操作可以使用take方法System.out.println("出队元素:"+queue.take());}System.out.println(queue);}}}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);}}public static void main(String[] args) {//创建线程池ThreadPoolExecutor pool = new ThreadPoolExecutor(0, 2, 0, TimeUnit.SECONDS, new PriorityBlockingQueuepool.execute(new OrederPayMent(i, new BigDecimal(String.valueOf(Math.random()*100))));}}}

上一篇:服务器被禁用怎么恢复?

下一篇:潘玮柏音乐下载攻略,轻松获取优质资源!