首頁 > 軟體

Java並行程式設計同步器CountDownLatch

2022-04-15 19:00:44

CountDownLatch

在日常開發中經常會遇到需要在主執行緒中開啟多個執行緒去並行執行任務,並且主執行緒需要等待所有子執行緒執行完畢後再進行彙總的場景。在 CountDownLatch 出現之前般都使用執行緒的join()方法來實現這一點,但是 join 方法不夠靈活,不能夠滿足不同場景的需要,所以 JDK 開發組提供了 CountDownLatch 這個類,我們前面介紹的例子使用 CoumtDownLatch 會更優雅。

使用CountDownLatch 的程式碼如下:

package LockSupportTest;

import java.util.concurrent.CountDownLatch;

public class JoinCountDownLatch {

    private static volatile CountDownLatch countDownLatch = new CountDownLatch(2);

    public static void main(String[] args) throws InterruptedException{

        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println("child threadOne over!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }
        });
        
        Thread threadTwo = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println("child threadOne over!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }
        });

        threadOne.start();
        threadTwo.start();
        System.out.println("wait all child thread over!!!");
        countDownLatch.await();
        System.out.println("all child thread over!");
    }

}

在如上程式碼中,建立了一個 CountDownLatch 範例,因為有兩個子執行緒所以建構函式的傳參為2。主執行緒呼叫countDownLatch.await()方法後會被阻塞。子執行緒執行完畢後呼叫 countDownLatch.countDown()方法讓 countDownLatch 內部的計數器減1,所有子執行緒執行完畢並呼叫 countDown()方法後計數器會變為0,這時候主執行緒的await()方法才會返回。其實上面的程式碼還不夠優雅,在專案實踐中一般都避免直接操作執行緒,而是使用 ExceutorService執行緒池來管理,使用ExcsuIwsnise時傳遞的引數是 Runable 或者 Callable物件,這時候你沒有辦法直接呼叫這些執行緒的join()方法,這就需要選擇使用CountDownLatch了。

將上面的程式碼修改為:

package LockSupportTest;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class JoinCountDownLatch2 {

    private static volatile CountDownLatch countDownLatch = new CountDownLatch(2);

    public static void main(String[] args) throws InterruptedException{

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println("child threadOne over!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }
        });
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println("child threadTwo over!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }
        });
        System.out.println("wait all child thread over!!!");
        countDownLatch.await();
        System.out.println("all child thread over!");
        executorService.shutdown();
    }

}

最後總結一下CountDownLatch與join()的區別。一個區別是,呼叫一個子執行緒的join()方法後,該執行緒會一直被阻塞直到子執行緒執行完畢,而 CountDownLatch 則使用計數器來允許子執行緒執行完畢或者在執行中遞減計數,也就是 CountDownLach 可以在子執行緒執行的任何時候讓 await() 方法返回而不一定必須等到執行緒結東。另外,使用執行緒池來管理執行緒時一般都是直接新增 Runable 到執行緒池,這時候就沒有辦法再呼叫執行緒的 join 方法了,就是說 counDownLatch 相比 join 方法讓我們對執行緒同步有更靈活的控制。

到此這篇關於Java並行程式設計同步器CountDownLatch的文章就介紹到這了,更多相關Java CountDownLatch內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com