CountDownLatch

CountDownLatch

CountDownLatch是一个同步器, 允许一个或多个线程执行完毕,再继续执行, 可以用来协调多个线程的同步。
CountDownLatch通过计数器实现, 计数器的初始值是线程的数量, 每当一个线程执行完毕, 计数器减1, 当计数器减为0或达到超时时间时, 等待的线程开始恢复执行。

应用场景

  • 某一个线程等待n个线程执行完毕, CountDownLatch初始化为CountDownLatch(n), 当某个任务线程执行执行结束时,调用countDown方法,计数器减1, 当计数器减为0时, 表示n个任务线程全部执行完毕,await的线程被唤醒, 开始执行。典型场景为,主线程等待所有子任务结束,继续下一步。 比如服务启动时等待多个组件加载完毕,启动服务。

  • 多个线程等待某个线程执行结束, 开始并发执行, CountDownLatch初始化为CountDownLatch(1), 每个等待线程启动时调用该CountDownLatch await方法被阻塞, 当主线程执行完成, 计数器减1, 同时唤醒多个等待线程开始执行。

重要方法

    // 构造器
    public CountDownLatch(int count) {}
    //
    public void await() throws InterruptedException {}
    //
    public boolean await(long timeout, TimeUnit unit) throws InterruptedException{}
    //
    public void countDown() {}
  • 构造器
    CountDownLatch的构造器仅有一个int参数, 代表阻塞的线程数量。
  • await
    调用此方法的线程会被挂起, 直到count值降为0才会被唤醒。
  • await(long timeout, TimeUnit unit)
    调用此方法的线程会被挂起, 直到count值降为0或超时才会被唤醒。
  • countDown
    调用此方法, count值减1

示例

  • 主线程等待n个线程执行结束
        final CountDownLatch countDownLatch = new CountDownLatch(10);
        for(int i=0; i<10; i++){
            final int finalI = i;
            Runnable thread = new Runnable() {
                @Override
                public void run() {
                    System.out.println(finalI);
                    countDownLatch.countDown();
                }
            };
            thread.run();
        }
        countDownLatch.await();
  • 并发执行
        ExecutorService service = Executors.newCachedThreadPool();
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        final CountDownLatch countDownLatch1 = new CountDownLatch(10);
        final int[] a = {0};
        for(int i=0; i<10; i++){
            Runnable thread = new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(a[0]);
                        countDownLatch.await();
                        a[0] += 1;
                        countDownLatch1.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            service.execute(thread);
        }
        countDownLatch.countDown();
        countDownLatch1.await();
        System.out.println(a[0]);

原理解析

TODO AQS

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容