併發-10-Condition

Coding挖掘機發表於2018-10-17

Condition是一個多執行緒間協調通訊的工具類,使得某個,或者某些執行緒一起等待某個條件(Condition),只有當該條件具備( signal 或者 signalAll方法被帶呼叫)時 ,這些等待執行緒才會被喚醒,從而重新爭奪鎖。

Condition例項實質上被繫結到一個鎖上。一個鎖內部可以有多個Condition,即有多路等待和通知。要為特定 Lock 例項獲得 Condition 例項,請使用其 newCondition() 方法。

Condition newCondition() 返回用來與當前Lock例項一起使用的Condition 例項。

類似於 object.wait()和object.notify()的功能。object.wait()與object.notify()需要結合synchronized使用。Condition需要結合ReentrantLock使用。

四種方法:

await()方法會使當前執行緒等待,同時釋放當前鎖,當其他執行緒中使用signal()時或者signalAll()方法時,執行緒會重新獲得鎖並繼續執行。或者當執行緒被中斷時,也能跳出等待。這和Object.wait()方法很相似。

awaitUninterruptibly()方法與await()方法基本相同,但awaitUninterruptibly()方法不會在等待過程中響應中斷。

singal()方法用於喚醒一個在等待中的執行緒。相對的singalAll()方法會喚醒所有在等待中的執行緒。這和Obejct.notify()方法類似。

condition.await()方法必須在lock.lock()與lock.unlock()方法之間呼叫。

public class ConditionExample{
    public static ReentrantLock lock = new ReentrantLock();
    public static Condition condition = lock.newCondition();

    public static void main(String[] args) {
        new Thread(() -> {
            lock.lock();
            out.println("執行緒1 獲得鎖");
            try {
                out.println("執行緒1 await");
                condition.await();
                out.println("執行緒1 再次獲得鎖");
            } catch (InterruptedException e) {
            } finally {
                out.println("執行緒1 釋放鎖");
                lock.unlock();
            }

        }).start();

        new Thread(() -> {
            lock.lock();
            out.println("執行緒2 獲得鎖");
            try {
                out.println("執行緒2 notifyAll");
                condition.signalAll();
            } finally {
                out.println("執行緒2 釋放鎖");
                lock.unlock();
            }

        }).start();
    }
}
複製程式碼

輸出:

執行緒1 獲得鎖
執行緒1 await
執行緒2 獲得鎖
執行緒2 notifyAll
執行緒2 釋放鎖
執行緒1 再次獲得鎖
執行緒1 釋放鎖
複製程式碼

經典例題:A、B、C依次列印

public class PrintOrderedABC {

    ReentrantLock lock = new ReentrantLock();
    Condition conditionA = lock.newCondition();
    Condition conditionB = lock.newCondition();
    Condition conditionC = lock.newCondition();
    String type = "A";

    void printA() {
        lock.lock();
        try {
            while (!StringUtils.equals(type, "A")) {
                conditionA.await();
            }
            out.println("print A");
        } catch (InterruptedException e) {
        }
        type = "B";
        conditionB.signal();
        lock.unlock();
    }

    void printB() {
        lock.lock();
        try {
            while (!StringUtils.equals(type, "B")) {
                conditionB.await();
            }
            out.println("print B");
        } catch (InterruptedException e) {
        }
        type = "C";
        conditionC.signal();
        lock.unlock();
    }

    void printC() {
        lock.lock();
        try {
            while (!StringUtils.equals(type, "C")) {
                conditionC.await();
            }
            out.println("print C");
        } catch (InterruptedException e) {
        }
        type = "A";
        conditionA.signal();
        lock.unlock();
    }

    public static void main(String[] args) {

        PrintOrderedABC printOrderedABC = new PrintOrderedABC();

        Thread ta = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                printOrderedABC.printA();
            }
        });

        Thread tb = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                printOrderedABC.printB();
            }
        });

        Thread tc = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                printOrderedABC.printC();
            }
        });

        ta.start();
        tb.start();
        tc.start();
    }
}
複製程式碼

相關文章