AQS理解之七——AQS中的条件队列
生活随笔
收集整理的這篇文章主要介紹了
AQS理解之七——AQS中的条件队列
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
AQS中的條件隊列
在AQS中還實現了一個類,ConditionObject,它實現了Condition接口,實現一個綁定在鎖上的條件隊列。
先看看他的uml圖。
主要方法
它實現了Condition接口,主要實現的方法是await和signal以及它們的帶時間參數方法。
條件隊列的一般用法:
當滿足某個條件時,通知正在等待這個條件的線程(signal)
當需要滿足某個條件才能繼續執行時,進行阻塞等待(await)
在AQS實現的ConditionObject中,使用了firstWaiter和lastWaiter的Node類來保存正在阻塞的線程節點。
在await時,是將當前線程插入鏈表,然后park線程,等待unpark。
signal時,將鏈表的第一個拿出來unpark。
signalAll則是拿出所有的進行unpark。
使用案例
在DelayQueue中使用到了Condition,如下:
在隊列插入時,如果插入的節點就是peek節點(說明之前隊列為空)則發出通知,顧名思義,發出的是一個available的通知,說明隊列現在又可以用了。
在隊列取出時,如果peek/first == null,說明隊列現在為空,不能拿出數據,需要等待,則available條件隊列開始等待,調用await,等待signal通知
private final Condition available = lock.newCondition();//在隊列插入時,如果插入的節點就是peek節點(說明之前隊列為空)則發出通知,顧名思義,發出的是一個available的通知,說明隊列現在又可以用了。 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();} } //在隊列取出時,如果peek/first == null,說明隊列現在為空,不能拿出數據,需要等待,則available條件隊列開始等待,調用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();} }總結
以上是生活随笔為你收集整理的AQS理解之七——AQS中的条件队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AQS理解之六,AQS的其他实现类
- 下一篇: ConcurrentHashMap源码学