1. 程式人生 > 程式設計 >Java併發程式設計入門(十四)CountDownLatch應用場景

Java併發程式設計入門(十四)CountDownLatch應用場景

Java極客  |  作者  /  鏗然一葉
這是Java極客的第 42 篇原創文章

一、應用場景

現實生活做中有很多這樣的場景:做F前需要等待A,B,C,D,E完成,A,E可以併發完成,沒有特定順序,例如:週末在家裡吃飯,有3件事情要做,爸爸做飯,媽媽做菜,兒子收拾餐桌,擺放碗筷。可以看到這個場景的特徵為:

1.在吃飯前有N件事情要做,每件事情都做完後才能吃飯,待處理的事情為N,每做完一件待處理事情就減少1,當待處理事情為0時,就可以吃飯了。

2.每件事情可以並行處理,沒有先後順序,因而提高了效率。

圍繞吃飯,整個過程如下:

在應用程式中處理並行操作時和上述場景類似,碰到這種場景時可以通過java併發工具CountDownLatch來實現。

二、Show me code

程式碼類結構如下:

I、EatingActivity.java

class EatingActivity implements Runnable {

    private CountDownLatch countDownLatch;

    public EatingActivity(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public void run() {
        try {
            //等待吃飯
System.out.println("Waiting for dinner..."); this.countDownLatch.await(); //所有事情做完後,await被喚醒,開始吃飯 System.out.println("Start eating..."); } catch (InterruptedException e) { e.printStackTrace(); } } } 複製程式碼

II、MakeRice.java

/**
 * 做飯
 */
class MakeRice implements Runnable {

    private CountDownLatch countDownLatch;

    public MakeRice(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public void run() {
        exec();
    }

    /**
     * 模擬做飯
     */
    private void exec() {
        try {
            System.out.println("Start making rice...");

            long millis = ((int)(1+Math.random()*(5-1+1))) * 1000;
            Thread.sleep(millis);
            System.out.println("Making rice is finished.");

            //待處理事情減1
            this.countDownLatch.countDown();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
複製程式碼

III、MakeDish.java

/**
 * 做菜
 */
class MakeDish implements Runnable {

    private CountDownLatch countDownLatch;

    public MakeDish(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public void run() {
        exec();
    }

    /**
     * 模擬做菜
     */
    private void exec() {
        try {
            System.out.println("Start making dish...");

            long millis = ((int)(1+Math.random()*(5-1+1))) * 1000;
            Thread.sleep(millis);
            System.out.println("Making dish is finished.");

            //待處理事情減1
            this.countDownLatch.countDown();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
複製程式碼

IV、CleanUpTable.java

/**
 * 收拾桌子
 */
class CleanUpTable implements Runnable {

    private CountDownLatch countDownLatch;

    public CleanUpTable(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    public void run() {
        exec();
    }

    /**
     * 模擬收拾桌子
     */
    private void exec() {
        try {
            System.out.println("Start making rice...");

            long millis = ((int)(1+Math.random()*(5-1+1))) * 1000;
            Thread.sleep(millis);
            System.out.println("Cleaning up table is finished.");

            //待處理事情減1
            this.countDownLatch.countDown();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
複製程式碼

V、CountDownLatchTest.java

/**
 * @ClassName CountDownLatchTest
 * @Description 驗證CountDownLatch
 * @Author 鏗然一葉
 * @Date 2019/10/7 22:32
 * @Version 1.0
 * javashizhan.com
 **/
public class CountDownLatchTest {

    public static void main(String[] args) {

        //為了吃飯,有3件事情要做
        CountDownLatch countDownLatch = new CountDownLatch(3);
        //吃飯活動
        Thread eatingActivity = new Thread(new EatingActivity(countDownLatch));
        eatingActivity.start();

        //做飯
        Thread makeRice = new Thread(new MakeRice(countDownLatch));
        //做菜
        Thread makeDish = new Thread(new MakeDish(countDownLatch));
        //收拾桌子
        Thread cleanUpTable = new Thread(new CleanUpTable(countDownLatch));

        //並行開始做事情
        makeRice.start();
        makeDish.start();
        cleanUpTable.start();
    }
}
複製程式碼

輸出日誌:

Waiting for dinner...
Start making rice...
Start making rice...
Start making dish...
Cleaning up table is finished.
Making rice is finished.
Making dish is finished.
Start eating...
複製程式碼

三、其他場景-拼團

拼團場景中,滿多少人後就可以成團,用到了計數器,看起來可以用CountDownLatch來實現,實際上沒有必要,因為拼團可以不是並行的,只要有計數器就可以實現。

四、總結

CountDownLatch的適用場景:

1.幾件事情完成之後才能開始另外一件事情。

2.需要做的幾件事情可以獨立完成,並且可以並行處理。

end.

Java併發程式設計(一)知識地圖
Java併發程式設計(二)原子性
Java併發程式設計(三)可見性
Java併發程式設計(四)有序性
Java併發程式設計(五)建立執行緒方式概覽
Java併發程式設計入門(六)synchronized用法
Java併發程式設計入門(七)輕鬆理解wait和notify以及使用場景
Java併發程式設計入門(八)執行緒生命週期
Java併發程式設計入門(九)死鎖和死鎖定位
Java併發程式設計入門(十)鎖優化
Java併發程式設計入門(十一)限流場景和Spring限流器實現
Java併發程式設計入門(十二)生產者和消費者模式-程式碼模板
Java併發程式設計入門(十三)讀寫鎖和快取模板
Java併發程式設計入門(十五)CyclicBarrier應用場景
Java併發程式設計入門(十六)秒懂執行緒池差別
Java併發程式設計入門(十七)一圖掌握執行緒常用類和介面
Java併發程式設計入門(十八)再論執行緒安全


Java極客站點: javageektour.com/