专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

AQS同步组件--CountDownLatch

CountDownLatch

CountDownLatch是在java1.5被引入的,跟它一起被引入的并发工具类还有CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue,它们都存在于java.util.concurrent包下。CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。 CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

调用CountDownLatch类的await()方法会一直阻塞,直到其他线程调用CountDown()方法使计数器的值减1,当计数器的值等于0则当因调用await()方法处于阻塞状态的线程会被唤醒继续执行。计数器是不能被重置的。这个类使用线程在达到某个条件后继续执行的情况。比如并行计算,计算量特别大,我可以将计算量拆分成多个线程进行计算,最后将结果汇总。

76_1.png

一个CountdownLatch 例子

@Slf4j
public class CountDownLatchExample1 {

    private final static int threadCount = 200;

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

        ExecutorService exec = Executors.newCachedThreadPool();

        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            exec.execute(() -> {
                try {
                    test(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        log.info("finish");
        exec.shutdown();
    }

    private static void test(int threadNum) throws Exception {
        Thread.sleep(100);
        log.info("{}", threadNum);
        Thread.sleep(100);
    }
}

结果:

20:13:26.716 [pool-1-thread-153] INFO com..concurrency.example.aqs.CountDownLatchExample1 - 152
20:13:26.711 [pool-1-thread-146] INFO com..concurrency.example.aqs.CountDownLatchExample1 - 145
20:13:26.716 [pool-1-thread-12] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 11
20:13:26.705 [pool-1-thread-95] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 94
20:13:26.711 [pool-1-thread-111] INFO com..concurrency.example.aqs.CountDownLatchExample1 - 110
20:13:26.706 [pool-1-thread-86] INFO com..concurrency.example.aqs.CountDownLatchExample1 - 85
20:13:26.716 [pool-1-thread-179] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 178
20:13:26.713 [pool-1-thread-23] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 22
20:13:26.716 [pool-1-thread-178] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 177
20:13:26.713 [pool-1-thread-148] INFO comconcurrency.example.aqs.CountDownLatchExample1 - 147
20:13:26.706 [pool-1-thread-54] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 53
20:13:26.713 [pool-1-thread-24] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 23
20:13:26.706 [pool-1-thread-65] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 64
20:13:26.716 [pool-1-thread-177] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 176
20:13:26.713 [pool-1-thread-144] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 143
20:13:26.713 [pool-1-thread-101] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 100
20:13:26.713 [pool-1-thread-98] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 97
20:13:26.713 [pool-1-thread-147] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 146
20:13:26.713 [pool-1-thread-120] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 119
20:13:26.713 [pool-1-thread-97] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 96
20:13:26.713 [pool-1-thread-117] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 116
20:13:26.707 [pool-1-thread-99] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 98
20:13:26.850 [main] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - finish

我们在线程之后都调用了countDown方法,在执行log之前调用了await方法,从而来保证打印日志时一定是在所有线程执行完。假设我们不使用CountDownLatch时结果会怎么样?

@Slf4j
public class CountDownLatchExample1 {

    private final static int threadCount = 200;

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

        ExecutorService exec = Executors.newCachedThreadPool();

        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            exec.execute(() -> {
                try {
                    test(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                }
//                finally {
////                    countDownLatch.countDown();
//                }
            });
        }
//        countDownLatch.await();
        log.info("finish");
//        exec.shutdown();
    }

    private static void test(int threadNum) throws Exception {
        Thread.sleep(100);
        log.info("{}", threadNum);
        Thread.sleep(100);
    }
}

这段代码打印结果就是,一开始就打印出了finish,因为这个打印是在主线程中执行。

20:13:26.850 [main] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - finish
20:13:26.716 [pool-1-thread-153] INFO com..concurrency.example.aqs.CountDownLatchExample1 - 152
20:13:26.711 [pool-1-thread-146] INFO com..concurrency.example.aqs.CountDownLatchExample1 - 145
20:13:26.716 [pool-1-thread-12] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 11
20:13:26.705 [pool-1-thread-95] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 94
20:13:26.711 [pool-1-thread-111] INFO com..concurrency.example.aqs.CountDownLatchExample1 - 110
20:13:26.706 [pool-1-thread-86] INFO com..concurrency.example.aqs.CountDownLatchExample1 - 85
20:13:26.716 [pool-1-thread-179] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 178
20:13:26.713 [pool-1-thread-23] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 22
20:13:26.716 [pool-1-thread-178] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 177
20:13:26.713 [pool-1-thread-148] INFO comconcurrency.example.aqs.CountDownLatchExample1 - 147
20:13:26.706 [pool-1-thread-54] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 53
20:13:26.713 [pool-1-thread-24] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 23
20:13:26.706 [pool-1-thread-65] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 64
20:13:26.716 [pool-1-thread-177] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 176
20:13:26.713 [pool-1-thread-144] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 143
20:13:26.713 [pool-1-thread-101] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 100
20:13:26.713 [pool-1-thread-98] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 97
20:13:26.713 [pool-1-thread-147] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 146
20:13:26.713 [pool-1-thread-120] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 119
20:13:26.713 [pool-1-thread-97] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 96
20:13:26.713 [pool-1-thread-117] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 116
20:13:26.707 [pool-1-thread-99] INFO com.concurrency.example.aqs.CountDownLatchExample1 - 98

文章永久链接:https://tech.souyunku.com/29138

未经允许不得转载:搜云库技术团队 » AQS同步组件--CountDownLatch

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们