[圖解Java]Condition

來源:互聯網
上載者:User

標籤:head   ima   als   問題   ola   編譯報錯   height   一個   mil   

圖解Condition0. demo

我先給出一個demo, 這樣大家就可以根據我給的這段代碼, 邊調試邊看源碼了. 還是那句話: 注意"My" , 我把ReentrantLock類 改名為了 "MyReentrantLock"類 , "Lock"類 改名為了"MyLock"類. 大家粘貼My Code的時候, 把相應的"My"都去掉就好了, 否則會編譯報錯哦.

import java.util.Scanner;import java.util.concurrent.locks.Condition;import java.util.function.Supplier;public class ConditionTest {    static final Scanner scanner = new Scanner(System.in);    static volatile String cmd = "";    private static MyReentrantLock lock = new MyReentrantLock(true);    private static Condition condition = lock.newCondition();    public static void main(String[] args) {        for (String name : new String[]{"w1", "w2", "w3", "w4", "w5", "w6"})            new Thread(() -> func(() -> lock, name)).start();        new Thread(() -> signalOne(() -> lock, "s")).start();        while (scanner.hasNext()) {            cmd = scanner.nextLine();        }    }    public static void func(Supplier<MyLock> myLockSupplier, String name) {        blockUntilEquals(() -> cmd, name);        myLockSupplier.get().lock();        System.out.println(name + "阻塞等待...");        try {            condition.await();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("釋放了" + name);        myLockSupplier.get().unlock();    }    public static void signalOne(Supplier<MyLock> myLockSupplier, String name) {        while (true) {            blockUntilEquals(() -> cmd, name);            myLockSupplier.get().lock();            condition.signal();            System.out.println("通知喚醒了一個等待...");            myLockSupplier.get().unlock();        }    }    private static void blockUntilEquals(Supplier<String> cmdSupplier, final String expect) {        while (!cmdSupplier.get().equals(expect))            quietSleep(1000);        clearCmd();    }    private static void quietSleep(int mills) {        try {            Thread.sleep(mills);        } catch (InterruptedException e) {            e.printStackTrace();        }    }    private static void clearCmd() {        cmd = "";    }}

使用例子在下面. 

首先輸入w1, 讓線程1執行await() . 然後輸入w2, 讓線程2執行await(). 然後輸入w3, 讓線程3執行await().

接下來輸入3次 s, 沒輸入一次s, 並按下斷行符號, 就會signal通知一個await等待.

1. 開始圖解Condition

想用ReentrantLock的Condition, 那麼就首先要有個ReentrantLock鎖.

執行個體化一個鎖, ReentrantLock裡只有一個成員變數sync.

sync執行個體裡面有四個成員變數.

分別表示:

          1. state - 鎖計數器

          2. exclusiveOwnerThread - 鎖的持有線程

          3. head - `等待隊列`的頭結點.

          4. tail - 指向`等待隊列`的最後一個元素

 然後咱們執行個體化了一個Condition. 

 當咱們輸入w1後, 第一個線程就申請了鎖, 並且申請成功.

 

 然後就執行到了await()方法.

將線程1封裝為Node節點, 然後waitState置為-2.  -2的含義是Condition.

 await()方法內部的第一個步驟就是把當前線程(線程1)插入到了`條件隊列`中.

 

然後就開始釋放當前線程(線程1)的鎖了, 而且是完全釋放, 一次就釋放掉全部重入次數哦, 也就是直接讓state等於0. 

釋放完鎖了, 然後掛起線程1.

 

然後讓線程2進行await.( 也就是前面的demo程式中在控制台輸入了w2.)

線程2執行await()之前當然是先擷取鎖了.

由於此時, 鎖是閒置. 所以線程2成功擷取到了鎖. 淡橙色的陰影部分為變化的內容:

  

擷取鎖之後, 線程2就該執行await()了:

 

 如, 將線程封裝為Node, 然後尾插到`條件隊裡`中, 只是await() 方法的第一步.

然後的操作, 就是完全釋放線程2的鎖, 然後掛起線程.

 

 

如果這個時候咱們在上面demo程式的控制台輸入"s", 那麼就會讓線程s 申請鎖, 申請成功後, 就會執行signal.

首先是線程s申請鎖成功:

 線程s成功擷取了鎖以後, 就是該執行signal()了.

 首先將`條件隊列`裡的第一個節點脫離出來:

 然後把waitState從-2改為0 :

隨後要做的就是把從`條件隊列`中脫離出來的Node(就是線程1對應的Node節點), 尾插到`等待隊列`中.

但是`等待隊列`此時還未被初始化, 所以插入到`等待隊列`之前, 要把`等待隊列`初始化了. 見:

 `等待隊列`初始化完了. 接下來就是把線程1對應的Node, 尾插到`等待隊列`中了:

 

然後將當前尾插的那個節點的前驅的waitState置為-1.  -1表示下一個節點等待著被喚醒. 

 

接下來就是線程s會執行到unlock(). 然後就會釋放鎖, 之後就是喚醒`等待隊列`中的第一個線程.

如此就介紹完了signal()

 

一個signal命令, 就把一個await的線程從`條件隊列中`移到了`等待隊列`中. 到了等待隊列中之後, 剩下的就是跟"鎖解鎖後, 喚醒下一個執行"這樣的步驟一樣了.

我覺得await方法就是將線程尾插到`條件隊列`中. signal()方法就是把條件隊列中的第一個元素, 尾插入到`等待隊列`中.

所以我覺得不必往下分析了.

也可能是我理所當然了, 有問題的話之後再補充.

[圖解Java]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.