AQS理解之七——AQS中的条件队列
AQS中的條件隊(duì)列
在AQS中還實(shí)現(xiàn)了一個類,ConditionObject,它實(shí)現(xiàn)了Condition接口,實(shí)現(xiàn)一個綁定在鎖上的條件隊(duì)列。
先看看他的uml圖。
主要方法
它實(shí)現(xiàn)了Condition接口,主要實(shí)現(xiàn)的方法是await和signal以及它們的帶時間參數(shù)方法。
條件隊(duì)列的一般用法:
當(dāng)滿足某個條件時,通知正在等待這個條件的線程(signal)
當(dāng)需要滿足某個條件才能繼續(xù)執(zhí)行時,進(jìn)行阻塞等待(await)
在AQS實(shí)現(xiàn)的ConditionObject中,使用了firstWaiter和lastWaiter的Node類來保存正在阻塞的線程節(jié)點(diǎn)。
在await時,是將當(dāng)前線程插入鏈表,然后park線程,等待unpark。
signal時,將鏈表的第一個拿出來unpark。
signalAll則是拿出所有的進(jìn)行unpark。
使用案例
在DelayQueue中使用到了Condition,如下:
在隊(duì)列插入時,如果插入的節(jié)點(diǎn)就是peek節(jié)點(diǎn)(說明之前隊(duì)列為空)則發(fā)出通知,顧名思義,發(fā)出的是一個available的通知,說明隊(duì)列現(xiàn)在又可以用了。
在隊(duì)列取出時,如果peek/first == null,說明隊(duì)列現(xiàn)在為空,不能拿出數(shù)據(jù),需要等待,則available條件隊(duì)列開始等待,調(diào)用await,等待signal通知
private final Condition available = lock.newCondition();//在隊(duì)列插入時,如果插入的節(jié)點(diǎn)就是peek節(jié)點(diǎn)(說明之前隊(duì)列為空)則發(fā)出通知,顧名思義,發(fā)出的是一個available的通知,說明隊(duì)列現(xiàn)在又可以用了。 public boolean offer(E e) {final ReentrantLock lock = this.lock;lock.lock();try {q.offer(e);if (q.peek() == e) {leader = null;available.signal();}return true;} finally {lock.unlock();} } //在隊(duì)列取出時,如果peek/first == null,說明隊(duì)列現(xiàn)在為空,不能拿出數(shù)據(jù),需要等待,則available條件隊(duì)列開始等待,調(diào)用await,等待signal通知 public E take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {for (;;) {E first = q.peek();if (first == null)available.await();else {long delay = first.getDelay(NANOSECONDS);if (delay <= 0)return q.poll();first = null; // don't retain ref while waitingif (leader != null)available.await();else {Thread thisThread = Thread.currentThread();leader = thisThread;try {available.awaitNanos(delay);} finally {if (leader == thisThread)leader = null;}}}}} finally {if (leader == null && q.peek() != null)available.signal();lock.unlock();} }總結(jié)
以上是生活随笔為你收集整理的AQS理解之七——AQS中的条件队列的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AQS理解之六,AQS的其他实现类
- 下一篇: ConcurrentHashMap源码学