CountDownLatch是闭锁的一种应用类,允许一个或多个线程等待某些操作完成,它是采用倒数检查控制线程的执行和等待。
概括的说,定义一个CountDownLatch对象并指定其需要倒数的线程数,通过await方法来阻塞线程,通过countDown方法来将计数器减1,如果计数器减到0,那么await方法的阻塞作用就消失了,当前线程则继续执行。说起来有些绕,一会看demo。
构造器:
CountDownLatch(int count)
Constructs a CountDownLatch initialized with the given count.
方法:
void | await() Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted. |
boolean | await(long timeout, TimeUnit unit) Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted, or the specified waiting time elapses. |
void | countDown() Decrements the count of the latch, releasing all waiting threads if the count reaches zero. |
long | getCount() Returns the current count. |
String | toString() Returns a string identifying this latch, as well as its state. |
示例代码:
import lombok.SneakyThrows;
import java.util.concurrent.CountDownLatch;
/**
* CountDownLatch
*/
public class CountDownLatchTest {
public void timeTasks(int nt,final Runnable task) throws InterruptedException {
final CountDownLatch startCDL = new CountDownLatch(1);
final CountDownLatch endCDL = new CountDownLatch(nt);
for (int i = 0; i < nt; i++) {
final int j = i;
Thread t = new Thread(){
public void run() {
try {
System.out.println("out i:"+j);
startCDL.await();
try {
System.out.println("inner i:"+j);
task.run();
}finally {
endCDL.countDown();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
}
Thread.sleep(2000);
startCDL.countDown();
endCDL.await();
}
public static void main(String[] args) throws InterruptedException {
CountDownLatchTest t = new CountDownLatchTest();
t.timeTasks(10, new Task());
}
}
class Task implements Runnable {
@SneakyThrows
@Override
public void run() {
//Thread.sleep(200);
System.out.println("task");
}
}
输出:
out i:0
out i:1
out i:2
out i:3
out i:5
out i:6
out i:7
out i:4
out i:8
out i:9
inner i:0
inner i:5
inner i:3
inner i:6
inner i:7
task
inner i:8
task
inner i:1
task
inner i:2
task
inner i:9
task
inner i:4
task
task
task
task
task
分析:demo代码创建了两个CountDownLatch,startCDL是控制各线程的开始执行时机,因为startCDL在代码20行对各线程中进行了阻塞,各线程初始化到此则阻塞了,各线程初始化完成后,主线程36行,解除了阻塞,然后各线程每执行完一个,通过endCDL.countDown()方法将计数器减1,直到endCDL的计数器为0,endCDL对主线程的阻塞也解除了。