Java并发之CountDownLatch

CountDownLatch是Java concurrent包下的一个同步工具。它可以让一个(或多个)线程等待,直到其他线程中的某些操作完成。

本质上是一个信号量,我们把它比作一个有N个插销的大门,它把等待(调用await)的线程挡住了, 直到其他线程把插销去完了(调用countDown减到0),这批线程才能执行。

下面是根据oracle官方文档改的一个例子:

/**
 * 
 * Sample usage: Here is a pair of classes in which a group of worker threads use two countdown latches:

 The first is a start signal that prevents any worker from proceeding until the driver is ready for them to proceed;
 The second is a completion signal that allows the driver to wait until all workers have completed.
 */
public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        new Driver().run();
    }
}

class Driver {
    static final int N = 5;
    public void run() throws InterruptedException {
        CountDownLatch startSignal = new CountDownLatch(1);

        CountDownLatch doneSignal = new CountDownLatch(N);
        for (int i=0; i<N; i++) {
            new Thread(new Worker(startSignal, doneSignal))
                    .start();
        }
        doSomething(); // don't let run yet
        startSignal.countDown(); // let all threads proceed
        doneSignal.await(); // wait for all to finish
        doSomething();
    }

    private void doSomething() {
        System.out.println("doSomething");
    }
}



class Worker implements Runnable {
    private CountDownLatch startSignal;
    private CountDownLatch doneSignal;

    public Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
        this.startSignal = startSignal;
        this.doneSignal = doneSignal;
    }

    public void run() {
        try {
            startSignal.await();
            doWork();
            doneSignal.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void doWork() {
        System.out.println("worker work.");
    }
}

把Driver看作是一个监工,Worker看作是工人,有5个。

  • 监工发号施令后,工人们才可以干活。所以工人干活前调用startSignal.await(), 直到监工调用startSignal.countDown() 后Worker后续doWork才开始执行。 
  • 工人们干完活后通知监工,监工才可以接着发号。所以监工调用doneSignal.await()在哪儿等着,直到工人们都干完活(调用5次doneSignal.countDown())后,才能接着执行。

看下执行结果,有助于理解整个工作过程和latch机制:

doSomething
worker work.
worker work.
worker work.
worker work.
worker work.
doSomething

原文地址:https://www.cnblogs.com/dreamysmurf/p/6119730.html