j.u.c.locks.condition

來源:互聯網
上載者:User

標籤:style   java   使用   os   io   strong   for   ar   

分享JUC中的Condition的比較少見,我見了大部分文章都是講其中的一個例子BoundedBuffer。今天先從Condition介面的幾個方法說起,然後在把BoundedBuffer搞死結了。來看看Condition在使用的時候需要注意什麼。

原始碼

上原始碼:(字數限時,原諒我把注釋都去掉了)

public interface Condition {        void await() throws InterruptedException;        void awaitUninterruptibly();        long awaitNanos(long nanosTimeout) throws InterruptedException;        boolean await(long time, TimeUnit unit) throws InterruptedException;        boolean awaitUntil(Date deadline) throws InterruptedException;        void signal();        void signalAll();}

Condtion介面主要是用來描述一個鎖的幾個狀態。具體建立方法如下

Condition notFull = lock.newCondition();

其實Condition的功能有點類似Object當中的wait和notify方法。但是稍做了加強。提供了多種wait的策略。另外用Condition的最大好處就是,一個鎖是可以擁有多個狀態的。如果用Object的wait和notify只能有一個。

具體看一下以下幾個wait方法:

    void await() throws InterruptedException;        void awaitUninterruptibly();        long awaitNanos(long nanosTimeout) throws InterruptedException;        boolean await(long time, TimeUnit unit) throws InterruptedException;        boolean awaitUntil(Date deadline) throws InterruptedException;

await()

解讀:會將當前線程設定成等待狀態,一直到有signal方法的觸發或者Interrupt的發生才會恢複狀態。當然interrupt了就直接拋異常了,不會繼續往下走

異常:InterruptedException

awaitUninterruptibly()

解讀:會將當前線程設定成等待狀態,一直到有signal方法的觸發。不會被Interrupt阻斷。

long awaitNanos(long nanosTimeout)

參數:最大的等待的時間

返回:實際的剩餘時間的估算(nanosTimeout - 實際等待時間)正值可以用於後續的繼續等待,例如消極式載入這樣的情境,可以讓程式繼續等待剩下的時間,完成計時。如果為0或者負數時,表示沒有剩餘時間了。

解讀:會將當前線程設定成等待狀態一直到設定的最大等待時間。當遇到singal或者Interrupt時才會恢複。

異常:InterruptedException

boolean await(long time, TimeUnit unit) 和 boolean awaitUntil(Date deadline)

參數:具體時間一個是間斷的時間,另一個是具體的時刻。但實質是一樣的。

解讀:具體等待一段時間或一個到一個時間點。如果遇到singal則返回True,否則返回false.

異常:InterruptedException

    void signal();        void signalAll();

void signal()

解讀:喚醒一個等待的線程,如果所有的線程都在等待此條件,則選擇其中的一個喚醒。在從 await 返回之前,該線程必須重新擷取鎖。

void signalAll()

解讀:喚醒所有線程,如果所有的線程都在等待此條件,則選擇其中的一個喚醒。在從 await 返回之前,該線程必須重新擷取鎖。


看一個例子:
public class BoundedBuffer {final Lock lock = new ReentrantLock();final Condition notFull = lock.newCondition();final Condition notEmpty = lock.newCondition();final Object[] items = new Object[2];int putptr, takeptr, count;public void put(Object x) throws InterruptedException {String threadName = Thread.currentThread().getName();System.out.println(threadName+" is waiting for lock");lock.lock();System.out.println(threadName+" got lock");try {while (count == items.length){System.out.println(threadName+" is waiting for notFull condition");notFull.await();System.out.println(threadName+" left notFull condition");}items[putptr] = x;if (++putptr == items.length){putptr = 0;}++count;notEmpty.signal();} finally {lock.unlock();}}public Object take() throws InterruptedException {String threadName = Thread.currentThread().getName();System.out.println(threadName+" is waiting for lock");lock.lock();System.out.println(threadName+" got lock");try {while (count == 0){System.out.println(threadName+" is waiting for notEmpty condition");notEmpty.await();System.out.println(threadName+" left notEmpty condition");}Object x = items[takeptr];if (++takeptr == items.length){takeptr = 0;}--count;notFull.signal();return x;} finally {lock.unlock();}}}

問得最多的一個問題:這裡的await有必要嗎?

while (count == 0){    System.out.println(threadName+" is waiting for notEmpty condition");    notEmpty.await();    System.out.println(threadName+" left notEmpty condition");}

回答:有必要,當count等於0的時候.如果沒有await釋放鎖,那麼其他線程會認為lock一直被佔有,將無法獲得鎖。


為了驗證這一點,寫了一個測試方法:

public class PutTask implements Runnable {BoundedBuffer bb = new BoundedBuffer();int count = 0;public PutTask(BoundedBuffer bb){this.bb = bb;this.count = 0;}@Overridepublic void run() {try {String threadName = Thread.currentThread().getName();bb.put(count);System.out.println(threadName+" put "+count);count++;} catch (InterruptedException e) {e.printStackTrace();}}}public class TakeTask implements Runnable {BoundedBuffer bb = new BoundedBuffer();public TakeTask(BoundedBuffer bb){this.bb = bb;}@Overridepublic void run() {try {System.out.println(Thread.currentThread().getName()+" take "+bb.take());} catch (InterruptedException e) {e.printStackTrace();}}}public class ConditionTest {public static void main(String[] args) throws InterruptedException{BoundedBuffer bb = new BoundedBuffer();PutTask putTask = new PutTask(bb);TakeTask takeTask1 = new TakeTask(bb);TakeTask takeTask2 = new TakeTask(bb);final ScheduledExecutorService service = Executors.newScheduledThreadPool(3);//service.scheduleAtFixedRate(putTask, 0, 1, TimeUnit.SECONDS);service.scheduleAtFixedRate(takeTask1, 0, 1, TimeUnit.SECONDS);service.scheduleAtFixedRate(takeTask2, 0, 1, TimeUnit.SECONDS);Thread.currentThread().sleep(3000l);Thread t = new Thread(putTask);t.start();}}

將notEmpty.await()注釋掉,執行的結果為

pool-1-thread-2 is waiting for lock

pool-1-thread-2 got lock

pool-1-thread-1 is waiting for lock

Thread-0 is waiting for lock

可以看到除了pool-1-thread-2獲得了鎖,其他線程都在等待鎖。但這個時候pool-1-thread-2被while(count==0)鎖死,無法跳出。程式進入死結。


恢複notEmpty.await()的注釋,執行的結果為

pool-1-thread-2 is waiting for lock

pool-1-thread-2 got lock

pool-1-thread-2 is waiting for notEmpty condition

pool-1-thread-1 is waiting for lock

pool-1-thread-1 got lock

pool-1-thread-1 is waiting for notEmpty condition

Thread-0 is waiting for lock

Thread-0 got lock

Thread-0 put 0

pool-1-thread-2 left notEmpty condition

pool-1-thread-2 take 0

pool-1-thread-2 is waiting for lock

pool-1-thread-2 got lock

pool-1-thread-2 is waiting for notEmpty condition








聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.