1.CountDownLatch -- 锁存器
有时在线程开发中遇到一些问题,如主线程启动了多个子线程,主线程需要在子线程都结束后再做一些处理,也就是说,主线程必须知道所有子线程都结束的时候。刚开始的时候自己写一个子线程列表,启动一个子线程,加1,结束一个子线程,减1,主线程不断循环等待,当子线程列表归零时就说明所有子线程都结束了。简单的任务还可以勉强使用,但大量是用线程池的时候,发现不靠谱了,研究发现,原来jdk中已经有了该工具类--CountDownLatch。
jdk文档:
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
用给定的计数初始化CountDownLatch
。由于调用了countDown()
方法,所以在当前计数到达零之前,await
方法会一直受阻塞。之后,会释放所有等待的线程,await
的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用CyclicBarrier
。
CountDownLatch
是一个通用同步工具,它有很多用途。将计数 1 初始化的CountDownLatch
用作一个简单的开/关锁存器,或入口:在通过调用countDown()
的线程打开入口前,所有调用await
的线程都一直在入口处等待。用N 初始化的 CountDownLatch
可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。
CountDownLatch
的一个有用特性是,它不要求调用 countDown
方法的线程等到计数到达零时才继续,而在所有线程都能通过之前,它只是阻止任何线程继续通过一个await
。
构造方法摘要 | |
---|---|
CountDownLatch(int count) 构造一个用给定计数初始化的CountDownLatch 。 |
方法摘要 | |
---|---|
|
await() 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。 |
|
await(long timeout,TimeUnit unit) 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。 |
countDown() 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。 |
|
getCount() 返回当前计数。 |
|
|
toString() 返回标识此锁存器及其状态的字符串。 |
实例:
public class Test {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3); //三个个工人的协作
Worker worker1 = new Worker("张三", 4000, latch);
Worker worker2 = new Worker("李四", 2000, latch);
Worker worker3 = new Worker("王五", 5000, latch);
worker1.start();
worker2.start();
worker3.start();
// 主线程阻塞,等待所有子线程完成(调用latch.countDown())
latch.await();
System.out.println("主线程:工作完成");
}
}
/**
* 工人类-子线程
*/
class Worker extends Thread{
private String name; // 工人姓名
private long time; // 工作时间(单位:毫秒)
private CountDownLatch latch; // 计数锁存器
public Worker(String name, long time, CountDownLatch latch) {
this.name = name;
this.time = time;
this.latch = latch;
}
private void doWork() throws I