Condition接口簡介


本博客系列是學習並發編程過程中的記錄總結。由於文章比較多,寫的時間也比較散,所以我整理了個目錄貼(傳送門),方便查閱。

並發編程系列博客傳送門

接口簡介

Condition可以看做是Obejct類的wait()notify()notifyAll()方法的替代品,與Lock配合使用。
當線程執行condition對象的await方法時,當前線程會立即釋放鎖,並進入對象的等待區,等待其它線程喚醒或中斷。

JUC在實現Conditon對象時,其實是通過實現AQS框架,來實現了一個Condition等待隊列,這個在后面講AQS框架時會詳細介紹,目前只要了解Condition如何使用即可。

接口定義

public interface Condition {

    void await() throws InterruptedException;

    long awaitNanos(long nanosTimeout) throws InterruptedException;
    
    boolean await(long time, TimeUnit unit) throws InterruptedException;

    boolean awaitUntil(Date deadline) throws InterruptedException;

    void signal();

    void signalAll();
}

使用示例

wait-notify模式的一個典型應用就是可以實現生產者-消費者模式。讓我印象很深是我畢業那年阿里巴巴校園招聘的一個筆試題:

有一個蘋果箱,有10個人向這個箱子中每次隨機放入一個蘋果,有10個人每次隨機從這個箱子中隨機拿走一個蘋果,同時需要滿足箱子中的蘋果總數不能超過50個。請用代碼實現上面的場景(不能使用並發集合框架)

這個題目使用wait-notify模式可以很好地解決。下面使用Condition模式來寫下。

public class AppleBoxConditon {

    private int appleCount;
    private static Lock lock = new ReentrantLock();
    private static Condition fullCondition = lock.newCondition();
    private static Condition emptyCondition = lock.newCondition();

    public void putApple() {
        lock.lock();
        try {
            while (appleCount >= 10) {
                try {
                    fullCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            appleCount++;
            System.out.println("放入一個,當前盒子中蘋果數:" + appleCount);
            emptyCondition.signalAll();
        } finally {
            lock.unlock();
        }
    }


    public void takeApple() {
        lock.lock();
        try{
            while (appleCount <= 0) {
                try {
                    emptyCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            appleCount--;
            System.out.println("拿走一個,當前盒子中蘋果數:" + appleCount);
            fullCondition.signalAll();
        }finally {
            lock.unlock();
        }
    }

    private static class AppleTaker implements Runnable {

        private AppleBoxConditon appleBox;

        public AppleTaker(AppleBoxConditon appleBox) {
            this.appleBox = appleBox;
        }

        @Override
        public void run() {
            while (true) {
                appleBox.takeApple();
                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    private static class ApplePutter implements Runnable {

        private AppleBoxConditon appleBox;

        public ApplePutter(AppleBoxConditon appleBox) {
            this.appleBox = appleBox;
        }

        @Override
        public void run() {
            while (true) {
                appleBox.putApple();
                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    public static void main(String[] args) {
        AppleBoxConditon appleBox = new AppleBoxConditon();


        for (int i = 0; i < 20; i++) {
            Thread t = new Thread(new AppleBoxConditon.ApplePutter(appleBox));
            t.setName("ApplePutter:"+i);
            t.start();
        }

        for (int i = 0; i < 20; i++) {
            Thread t = new Thread(new AppleBoxConditon.AppleTaker(appleBox));
            t.setName("AppleTaker:"+i);
            t.start();
        }

    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM