栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ArrayBlockingQueue详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ArrayBlockingQueue详解

ArrayBlockingQueue是由数组实现的阻塞队列,是BlockingQueue的实现类。

特点:

是一个有界的数组,创建的时候传入初始队列大小,

底层采用的是ReentrantLock实现阻塞和用condition条件队列

每次只能有一个线程读写操作,也就是说生产者和消费者公用一把锁,效率其实一般

底层采用数组存储

=================================================================

Node节点,节点存放pre和next节点,还有一个waitStatus状态,还有存放线程的Thread对象。

讲下CLH同步阻塞队列,是一个双向链表,有个head头和tail尾,操作的元素是Node节点

condition阻塞队列,是个单向链表,有个firstWaiter,和lastWaiter,也是用Node节点

================================================================

创建ArrayBlockingQueue:

传入队列初始大小capacity,初始化一个Object数组,初始化一个ReentrantLock,默认非公平锁,初始化两个condition条件队列,notEmpty(处理消费者线程的)和notFull(处理生产者线程的)

生产过程 put过程:

调用put方法,调用ReentrantLock的lock.lockInterruptibly加可中断锁,(ReentrantLock加锁其实底层是一个CLH队列,维护一个volatile int state=0状态,state=0表示没有线程在加锁,state大于0有线程加锁,采用cas操作进行修改state。没抢到锁的会进入CLH队列,然后SupportLock.park进行阻塞,等待抢到锁的SupportLock.unpark释放锁唤醒。大概是这样)

如果获取到锁,判断数组是否满了(count==数组大小),如果没有满,调用enqueue方法写入数组,维护count++,给notEmpty消费者条件队列发送一个信号(notEmpty.signal()),调用doSinal方法,通知存放在condition队列的消费者Node,enq入队到CLH队列,因为必须要到CLH队列,才能获取到ReentrantLock的锁;

如果数组满了,则notFull条件队列会调用await方法阻塞,把当前获取锁的线程node写入到notFull队列,调用addConditionWaiter进行写入condition入队,      condition里node的waitStatus状态是condition(-2),入完队尝试释放锁,调用fullyRelease方法,在调用release方法释放锁,释放锁会唤醒CLH队列中head后面的第一个node,如果这个node还是生产者,会把生产者node写入到notFull条件队列中,判断如果不在CLH同步队列,会把写入condition队列的node进行阻塞park,等待消费者take消费后singal通知,唤醒在notNull等待队列的生产者

写入成功后调用lock.unlock释放锁。

消费过程take过程:

调用take方法,调用ReentrantLock的lock.lockInterruptibly加可中断锁,判断数组数量是否大于0,如果有数据则调用dequeue进行出队消费,并给notFull发送一个signal通知,让在notFull条件等待队列的生产者enq写入CLH同步队列去获取lock锁,然后唤醒CLH队列第一个node节点。

如果数组为空,则让消费者node进行await阻塞,写入到notEmpty条件队列中,这个过程其实和生产者写入notFull条件队列是一样的。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/736838.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号