Java并发编程--JUC并发工具类之CountDownLatch
摘要
-
本文介绍CountDownLatch相关技术
-
本文基于
jdk1.8
CountDownLatch介绍
-
CountDownLatch
提供了一种同步机制,用于在多个线程之间进行等待和协调。 -
CountDownLatch
是一种计数器,它允许一个或多个线程等待其他线程完成操作后再继续执行。 -
CountDownLatch
的工作原理很简单,它通过一个初始计数器来初始化,该计数器表示需要等待的线程数。当一个线程完成了它的操作时,计数器会减少。当计数器达到零时,所有等待的线程都会被释放,可以继续执行。
CountDownLatch的常用方法
方法 | 描述 |
---|---|
CountDownLatch(int count) |
构造函数,创建一个CountDownLatch对象,指定初始计数器的值为count |
void await() |
阻塞调用此方法的线程,直到计数器达到零。如果计数器的值不为零,则调用线程将被阻塞 |
boolean await(long timeout, TimeUnit unit) | 阻塞调用此方法的线程,直到计数器达到零或超过指定的等待时间。如果计数器的值不为零,则调用线程将被阻塞 |
void countDown() |
计数器减少一个单位。当一个线程完成了它的操作时,应该调用此方法来减少计数器的值 |
long getCount() |
获取当前计数器的值 |
代码示例
示例1–多任务完成后合并汇总
1 | import java.util.concurrent.CountDownLatch; |
-
在上述示例中,主线程创建了一个
CountDownLatch
对象,并指定初始计数器的值为3
。然后,主线程启动了三个工作线程,并将CountDownLatch
对象传递给它们。 -
每个工作线程在执行任务前会输出开始信息,然后模拟执行任务的耗时操作(这里用
Thread.sleep(2000)
模拟),最后输出任务完成信息。在任务完成后,每个工作线程都会调用latch.countDown()
来减少计数器的值。 -
主线程通过调用
latch.await()
方法阻塞自己,等待所有工作线程完成任务。当计数器的值为零时,主线程被唤醒,继续执行,输出"All threads have completed their tasks."的信息。
示例2–模拟实现百米赛跑
1 | public class CountDownLatchDemo { |
-
上述代码展示了使用
CountDownLatch
进行比赛场景的模拟。裁判(begin
)初始计数为1
,代表裁判等待的条件为所有参赛者准备就绪。玩家(end
)初始计数为8
,代表参赛者的数量。 -
每个参赛者都会在准备好后等待裁判的指令,然后开始跑步,跑到终点后计数器减一。裁判会在等待
5
秒后吹哨,开始比赛。当所有玩家到达终点后,比赛结束。
CountDownLatch通常用于以下场景
-
主线程等待多个子线程完成任务后再继续执行。
-
多个子线程等待某个共享资源的初始化完成后再开始执行。
-
协调多个线程执行的时间点。
使用CountDownLatch的注意事项
-
初始化计数器的值:在创建
CountDownLatch
对象时,需要确定初始计数器的值。该值应该与等待的线程数量一致,以确保所有线程完成任务后计数器的值为0。 -
await()
方法的阻塞:调用await()
方法会使当前线程阻塞,直到计数器的值变为0
。需要确保在调用await()
方法之前,计数器的值能够达到0
。否则,调用线程将一直被阻塞,无法继续执行。 -
countDown()
方法的调用:在每个线程完成任务后,都需要调用countDown()
方法来减少计数器的值。确保在适当的位置调用countDown()
,否则计数器的值无法正确减少,导致主线程一直被阻塞。 -
异常处理:在使用
CountDownLatch
时,需要注意处理可能抛出的InterruptedException
异常。例如,在调用await()
方法时需要捕获InterruptedException
,并进行适当的处理。 -
CountDownLatch
的复用:CountDownLatch
对象在计数器值减少到0
后,可以重用。可以通过重新设置计数器的值来复用CountDownLatch
对象,以便在新的场景中再次使用。 -
计数器值的访问:可以使用
getCount()
方法获取当前计数器的值,以便在需要时查看计数器的状态。