CountDownLatch 协调线程

JDK8 都快要出来了,在 JDK 5 中仍有许多好宝贝值得去挖掘。提到 JDK5 我们或许只知道它给了我们泛型,其实还有那个并发包 java.util.concurrent 却不那么引人注目,其实就是 NIO。

若是并发包是在某个 JDK 版本中单独奉上,反响就不同了,想想 JDK 6 似乎未带来多少改变--至少对于编程者来说没有明显感受。java.util.concurrent 包中的东西对于我们处理线程带来了很大的便利,例如线程池,线程同步,Future, Callable 等。

这里我记录一下 CountDownLatch 的使用,在此之前在处理

线程 A 等待线程 B,C,D 全部执行完后才继续执行 (比如要每个线程都访问一个 Web 服务,等所有的请求响应成功后进行结果处理)

这样场景的时候,我一般能想到的办法是,初始一个计数器,线程 B,C,D 各自初始化的时候,计数器加一,然后 A 线程等待,每个线程执行完后计数器减一,当计数器为 0 时表明所有任务执行完毕,就通知 A 可以开始运作起来。但这样的方案还是得小心的处理好同步的问题。

这可以用 JDK 5  java.util.concurrent.CountDownLatch,它的实现原理基本与上一致。也是需要任务在执行完毕后执行一下 countDown() 方式使得计数减一,当为 0 时,A 被唤醒。CountDown 就是倒计数,Latch 是门拴的意思,可以理解为某一线程等待所有它关注的线程全部出去(或进来)后把门拴上。

看个示例:

输出是:

AlertService is Up
CacheService is Up
All services are up, Application is starting now

PlayFramework 的 controller 中的 await 和这很相拟,它较喜欢用 Promise 这个词。

CountDownLatch 变成 0 后就不能重用了,如果想要能重用的就使用 java.util.concurrent.CyclicBarrier 吧,它用到了 ReentrantLock 的概念。

参考:1. What is CountDownLatch in Java - Concurrency Example Tutorial
            2. What is CyclicBarrier Example in Java 5 – Concurrency Tutorial

本文链接 https://yanbin.blog/countdownlatch-threads/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

1 Comment
Inline Feedbacks
View all comments
预流
10 years ago

JDK5的线程相关的API非常值得研究。