CountDownLatch 的使用

97 阅读1分钟

CountDownLatch

用于等待多个线程处理完成任务后才能进行下一步的操作

构造函数

public CountDownLatch(int count) {
    if (count < 0) throw new IllegalArgumentException("count < 0");
    this.sync = new Sync(count);
}

只有一个构造函数,一个 int 类型的参数 cout ,需要等待的线程数

方法

// 进行无限时等待 count 个线程执行完成
public void await() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);
}
// 进行等待timeout长的时间 或者 count 个线程执行完成
public boolean await(long timeout, TimeUnit unit)
    throws InterruptedException {
    return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}

// 表示一个线程已完成任务
public void countDown() {
    sync.releaseShared(1);
}
// 获取当前还剩多少个线程没有完成任务
public long getCount() {
    return sync.getCount();
}
  • 使用给定的计数 count 初始化 CountDownLatch。
  • 当前的await方法将一直阻塞,除非使用 countDown(方法的调用 直到当前计数达到零为止,此后,所有等待线程将被释放,并且随后的所有await调用将立即返回。
  • 这是一种一次性现象-无法重置计数。 如果需要用于重置计数的版本,请考虑使用CyclicBarrier。

使用示例


public class Driver {

    public static final int N = 5;

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

    void done() throws InterruptedException {
        CountDownLatch startSignal = new CountDownLatch(1); 
        CountDownLatch doneSignal = new CountDownLatch(N);
        for (int i = 0; i < N; ++i){
            // 创建和启动线程
            new Thread(new Worker(i, startSignal, doneSignal)).start();
        }


        System.out.println("Driver : before start ...");
        startSignal.countDown();      // 让所有线程同时开始
        doneSignal.await();           // 等待所有线程执行完成  }}
        System.out.println("Driver : all work finish ...");
    }

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

        private String name;

        Worker(int index, CountDownLatch startSignal, CountDownLatch doneSignal) {
            this.name = "Worker-" + index;
            this.startSignal = startSignal;
            this.doneSignal = doneSignal;
        }

        public void run() {
            try {
                startSignal.await();  // 所有的Worker线程启动时都等待启动信号
                doWork();
                doneSignal.countDown(); // 执行完任务后线计数减1
            } catch (InterruptedException ex) {
            } // return;
        }

        void doWork() {
            System.out.println(name + " : doWork...");
        }
    }
}

輸出

Driver : before start ...
Worker-0 : doWork...
Worker-1 : doWork...
Worker-2 : doWork...
Worker-4 : doWork...
Worker-3 : doWork...
Driver : all work finish ...