概述
CountDownLatch
是 JUC
包下的一个重要的并发工具,它是一个线程协同作业的工具,使某些线程一直处于等待状态,直到另外的线程完成任务后再执行。
主要方法
CountDownLatch
主要靠内部的一个计数器来实现同步功能,其过程具有不可重复性。
countDown()
方法:计数器的值-1
。getCount()
方法:获取当前计数器的值。await()
方法:当计数器的值不为0
时,将阻塞所有调用此方法的线程,一直到计数器的值为0
时,才会唤醒所有被此CountDownLatch
对象阻塞的线程。await(long timeout, TimeUnit unit)
方法:在await()
方法的基础上,增加了超时时间,以及增加了boolean
类型的返回值。- 当
timeout
的值小于或等于0
时,将不会等待,若此时计数器的值为0
,则返回true
,否则返回false
。 - 当计数器在超时时间内,值归
0
了,则会正常返回true
,并执行唤醒操作。 - 当超过了这个超时时间,计数器的值还未归
0
,则会返回false
,也会执行唤醒操作。
- 当
举例实现
现有代码如下:
static class MyRunnable implements Runnable {
private int id;
private CountDownLatch countDownLatch;
public MyRunnable(int id, CountDownLatch countDownLatch) {
this.id = id;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println("线程 :"+id+"正在执行......");
try {
Thread.sleep((int)(2000+(Math.random()*1000)));
}catch (Exception ignored) {
}
countDownLatch.countDown();
System.out.println("线程 :"+id+"执行结束!!!!!!");
}
}
static class Runnable1 implements Runnable {
private CountDownLatch countDownLatch;
public Runnable1(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println("线程 Runnable 1 开始执行, 需要等到 CountDownLatch 的计数为0时才会执行下一步操作");
try {
countDownLatch.await();
System.out.println("线程 Runnable 1 终于执行完毕, 此时 CountDownLatch 中的计数为: "+countDownLatch.getCount());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(5);
new Thread(new Runnable1(countDownLatch)).start();
for (int i = 0;i<5;i++) {
new Thread(new MyRunnable(i, countDownLatch)).start();
}
countDownLatch.await();
System.out.println("全部线程执行结束, 现在主线程可以开始执行下一步操作, 此时 CountDownLatch 中的计数为: "+countDownLatch.getCount());
}
代码运行结果为:
线程 Runnable 1 开始执行, 需要等到 CountDownLatch 的计数为0时才会执行下一步操作
线程 :0正在执行......
线程 :2正在执行......
线程 :3正在执行......
线程 :4正在执行......
线程 :1正在执行......
线程 :3执行结束!!!!!!
线程 :2执行结束!!!!!!
线程 :1执行结束!!!!!!
线程 :0执行结束!!!!!!
线程 :4执行结束!!!!!!
线程 Runnable 1 终于执行完毕, 此时 CountDownLatch 中的计数为: 0
全部线程执行结束, 现在主线程可以开始执行下一步操作, 此时 CountDownLatch 中的计数为: 0
可以看到,Runnable1
中的 run()
方法中的第一行打印语句最先执行,随后调用 countDownLatch.await()
方法后即被阻塞 ,其后一直等到所有的 MyRunnable
线程都执行结束后(即 CountDownLatch
的内部计数器值为 0
时),第二行打印语句才被执行。主线程中的打印语句亦如此。