高併發程式設計-Condition深入解析
概述
Condition介面位於java.util.concurrent.locks包下,實現類有 AbstractQueuedLongSynchronizer.ConditionObject和 AbstractQueuedSynchronizer.ConditionObject。Condition將Object監視器方法(wait、notify和 notifyAll)分解成截然不同的物件,以便通過將這些物件與任意Lock實現組合使用。其中,Lock替代了synchronized方法的使用及作用,Condition替代了Object監視器方法的使用及作用。Condition的await方法代替Object的wait;Condition的signal方法代替Object的notify方法;Condition的signalAll方法代替Object的notifyAll方法。Condition例項在使用時需要繫結到一個鎖上,可以通過newCondition方法獲取Condition例項。Condition實現可以提供不同於Object監視器方法的行為和語義,比如受保證的通知排序,或者在執行通知時不需要保持一個鎖。
樣例程式碼
下面的程式碼演示了Condition簡單使用的樣例。
public class ConditionDemo { @Test public void test() { final ReentrantLock reentrantLock = new ReentrantLock(); final Condition condition = reentrantLock.newCondition(); new Thread(new Runnable() { @Override public void run() { try { reentrantLock.lock(); System.out.println(Thread.currentThread().getName() + "在等待被喚醒"); condition.await(); System.out.println(Thread.currentThread().getName() + "恢復執行了"); } catch (InterruptedException e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } } }, "thread1").start(); new Thread(new Runnable() { @Override public void run() { try { reentrantLock.lock(); System.out.println(Thread.currentThread().getName() + "搶到了鎖"); condition.signal(); System.out.println(Thread.currentThread().getName() + "喚醒其它等待的執行緒"); } catch (Exception e) { e.printStackTrace(); } finally { reentrantLock.unlock(); } } }, "thread2").start(); } }
輸出結果如下所示:
thread1在等待被喚醒 thread2搶到了鎖 thread2喚醒其它等待的執行緒 thread1恢復執行了
建立Condition例項
通過Lock介面實現類的newCondition方法獲取Condition例項,例如如下程式碼:
ReentrantLock reentrantLock = new ReentrantLock(); Condition condition = reentrantLock.newCondition();
常用方法
await()
呼叫await方法後,當前執行緒在接收到喚醒訊號之前或被中斷之前一直處於等待休眠狀態。呼叫此方法時,當前執行緒保持了與此Condition有關聯的鎖,呼叫此方法後,當前執行緒釋放持有的鎖。此方法可以返回當前執行緒之前,都必須重新獲取與此條件有關的鎖,線上程返回時,可以保證它保持此鎖。
await(long time,TimeUnit unit)
呼叫此方法後,會造成當前執行緒在接收到喚醒訊號之前、被中斷之前或到達指定等待時間之前一直處於等待狀態。呼叫此方法時,當前執行緒保持了與此Condition有關聯的鎖,呼叫此方法後,當前執行緒釋放持有的鎖。time引數為最長等待時間;unit引數為time的時間單位。如果在從此方法返回前檢測到等待時間超時,則返回 false,否則返回true。此方法可以返回當前執行緒之前,都必須重新獲取與此條件有關的鎖,線上程返回時,可以保證它保持此鎖。
awaitNanos(long nanosTimeout)
該方法等效於await(long time,TimeUnit unit)方法,只是等待的時間是 nanosTimeout指定的以毫微秒數為單位的等待時間。該方法返回值是所剩毫微秒數的一個估計值,如果超時,則返回一個小於等於0的值。可以根據該返回值來確定是否要再次等待,以及再次等待的時間。
awaitUninterruptibly()
呼叫此方法後,會造成當前執行緒在接收到喚醒訊號之前一直處於等待狀態。如果在進入此方法時設定了當前執行緒的中斷狀態,或者在等待時,執行緒被中斷,那麼在接收到喚醒訊號之前,它將繼續等待。當最終從此方法返回時,仍然將設定其中斷狀態。呼叫此方法時,當前執行緒保持了與此Condition有關聯的鎖,呼叫此方法後,當前執行緒釋放持有的鎖。此方法可以返回當前執行緒之前,都必須重新獲取與此條件有關的鎖,線上程返回時,可以保證它保持此鎖。
awaitUntil(Date deadline)
呼叫此方法後,會造成當前執行緒在接收到喚醒訊號之前、被中斷之前或到達指定最後期限之前一直處於等待休眠狀態。呼叫此方法時,當前執行緒保持了與此Condition有關聯的鎖,呼叫此方法後,當前執行緒釋放持有的鎖。此方法可以返回當前執行緒之前,都必須重新獲取與此條件有關的鎖,線上程返回時,可以保證它保持此鎖。
signal()
喚醒一個等待執行緒,如果所有的執行緒都在等待此條件,則選擇其中的一個喚醒。在從await返回之前,該執行緒必須重新獲取鎖。
signalAll()
喚醒所有等待執行緒,如果所有的執行緒都在等待此條件,則喚醒所有執行緒。 在從await返回之前,每個執行緒必須重新獲取鎖。
作者:JavaQ
連結:https://www.jianshu.com/p/df43904621c2