JUC相关连载五---基于条件队列和ReentrantLock的阻塞队列(Java劝退师)

      条件队列的典型的实现就是:阻塞队列。有元素就通知线程处理,无元素就阻塞线程等待。看条件队列,先看其 等待/通知 的实现。

      1、ConditionObject的结构:

       

        

      2、ConditionObject是interface Condition的实现类。其主要的接口是await和signal:

await():不限时等待。
await(long time, TimeUnit unit):限时等待,可以指定时间单位。
awaitNanos(long nanosTimeout):限时等待,时间单位为纳秒。
awaitUninterruptibly():不可中断的限时等待。
awaitUntil(Date deadline):限时等待,指定超时时间为将来的某个时间点。
signal():通知等待队列里节点(firstWaiter指向的第一个Node)。
signalAll():通知等待队列里所有的节点。

     先看等待 await方法(注意下里面的这个checkInterruptWhileWaiting方法)

checkInterruptWhileWaiting 方法里调用了 transferAfterCancelledWait。到这里证明是被signal唤醒了。如果当前节点还没有被加入到同步队列,则让出cpu时间片继续查询是否已经加入。

    唤醒 signal方法

 

Condition.await/Condition.signal 与Object.wait/Object.notify区别:

前者是AQS和lock在jdk实现,后者是 synchronized JVM实现

以上就是条件队列的通知与唤醒的实现。现在看下阻塞队列是如何依赖此实现的。

阻塞队列的实现主要是基于 Condition队列的条件中转 以及 ReentrantLock来实现的(一个notEmpty队列记录的是取元素,notFull记录的是put元素)。

流程(ArrayBlockingQueue为列,以下简称 abq):

1、初始化大小为1的阻塞队列abq.

2、线程p1放入一个元素进abq。

3、放入后通知notEmpty条件队列里面阻塞的现线程来取数据,如果notEmpty中此时没有等待排队的线程,那此时abq长度为1.

4、线程p2又来放一个元素进abq。

5、此时abq在放入前已经满了,而此时线程2不能再放入了,它将进入一个notFull的队列等待。

6、此时一个一个线程 t1来取,取完之后abq的长度为0,小于最大长度1,则取完后通知p2继续往里面放。

7、p2被唤醒signal之后,从原来的notFull队列转移到同步队列当中。转移到同步队列中的方法上面已经讲了在 signal方法中

8、同样的如果元素都被取完还有线程来取,则加入到notEmpty队列中等待有线程put后被其signal。

注:这里一定要区分条件队列和同步队列的关系,以及条件队列向同步队列的转移。同步队列永远不回去唤醒条件队里的线程。

除此之外的 DelayQueue等队列,都是以此原来的一些功能拓展。

下面一次更新讲的线程池,就是根据阻塞队列来进行的。。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值