1. 程式人生 > >Java並發工具類之CountDownLatch

Java並發工具類之CountDownLatch

clas 允許 his wait方法 輸出 throw 引用 excel文件 inter

  CountDownLatch允許一個或則多個線程等待其他線程完成操作。

  假如我們有這樣的需求:我們需要解析一個excel文件中的多個sheet,我們可以考慮使用多線程,每一個線程解析excel中的一個sheet表格,等所有的線程都完成解析之後,程序提示解析完成,輸出解析結果。要實現這個需求,最簡單的方式是使用Thread類的join方法,等待所有的線程都完成解析之後再提示解析完成,我們可以用一下代碼完成解析:

public class ReadExcelSheetsUserThreadJoinTest {

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

        Thread sheet1Thread 
= new Thread(new Runnable() { @Override public void run() { System.out.println("解析sheet1"); } }); Thread sheet2Thread = new Thread(new Runnable() { @Override public void run() { System.out.println("
解析sheet2"); } }); sheet1Thread.start(); sheet2Thread.start(); sheet1Thread.join(); sheet2Thread.join(); System.out.print("所有的表格解析完成"); } }

輸出結果:

解析sheet1
解析sheet2
所有的表格解析完成

  join用於讓當前執行線程等待join線程執行結束,其執行原理是不停的檢查join線程是否存活,如果join線程存活,則讓當前線程永遠等待。代碼如下,其中wait(0)表示永遠等待。

while (isAlive()) {
       wait(0);
}

  直到join線程終止後,線程的this.notifyAll()方法被調用,大家可以參考JVM源碼,查看notifyAll方法被調用的過程。

  在JDK1.5之後,Java的並發包提供了CountDownLatch,CountDownLatch也可以實現線程的join功能,並且比Thread的join方法提供的功能更多,使用CountDownLatch實現上述需求的代碼如下:

public class ReadExcelSheetsUseCountDownLatchTest {

    private static CountDownLatch countDownLatch = new CountDownLatch(2);

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

        Thread sheet1Thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("解析sheet1");
                countDownLatch.countDown();
            }
        });

        Thread sheet2Thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("解析sheet2");
                countDownLatch.countDown();
            }
        });

        sheet1Thread.start();
        sheet2Thread.start();
        countDownLatch.await();
        System.out.print("所有的表格解析完成");
    }

}

  CountDownLatch的構造函數接收一個int類型的參數作為計數器,如果你想等待n個點完成,就傳入n,我們調用CountDownLatch的countDown方法的時候,n就會減1,await方法會阻塞當前線程直到n變為0,由於CountDownLatch的countDown方法可以用在任何地方,因此這裏的n可以是n個線程,也可以是1個線程裏面的n個步驟。編程的時候只需要把CountDownLatch的引用傳到線程即可。

  有時候,我們不希望執行線程一直等待下去,這個時候我們可以使用CountDownLatch的await(long time,TimeUnit unit),這個方法在特定的時間之後就不會再阻塞執行線程,當然join也有類似的重載方法。

  計數器必須大於等於0,只是等於0時候,計數器就是零,調用await方法時不會阻塞當前線程。CountDownLatch不可能重新初始化或者修改CountDownLatch對象的內部計數器的值。一個線程調用countDown方法happen-before,另外一個線程調用await方法。

Java並發工具類之CountDownLatch