前言
少商剑:剑路雄劲,石破天惊,CountDownLatch以其强大而直接的方式控制线程等待和同步,具有明确而有力的作用。
CountDownLatch是一个同步工具类,它是根据计数器实现的,构造函数初始时会指定总的计数数量,每调用一次countDown数量会减一,当数量为0时,闸门将会放开,await等待的线程进而继续执行。
例如,小红,小兰,小明一起去野餐,他们约定先一起到公园门口再开始活动,这时计数器初始值就是3,当小红到达目的地,计数器减1,小红继续等待小兰和小明;小兰到达计数器再减1,再一起等待小明的到达;小明到达,数量就减为0了,他们三人再一起进行活动。
一个简单的动画流程:
CountDownLath方法详解
- 构造函数 CountDownLatch(int count):count为计数器的初始值(一般count就是线程数)
- countDown():每调用一次count数减1(一般当线程完成任务后调用)
- getCount():获取当前计数器count的值。
- await():一直等待,直到计数器count值为0。
- boolean await(long timeout, TimeUnit unit):一直等待,直到count值为0,或者过了timeout时间后停止等待。如果是count值为0停止的等待,返回的boolean就为true;如果是过了timeout时间后停止的等待,返回的boolean就为false。
举个栗子🌰
组装加工一台电脑,我们需要加工CPU、主板、内存、显卡、电源等部件,如果进行串行加工,那需要等待CPU加工完再加工主板,那耗时就是所有部件的总和,但如果像工厂那样,流水线作业并行处理,加工CPU的同时,其他所有部件也一起加工,等待所有的部件加工完,我们再组装成电脑,这样效率快了很多。
csharp
public class CountDownLatchCase {
public static void produce() throws InterruptedException {
List<Task> taskList = new ArrayList<>();
taskList.add(new Task("CPU",2000L));
taskList.add(new Task("主板",800L));
taskList.add(new Task("内存",500L));
taskList.add(new Task("显卡",1000L));
taskList.add(new Task("电源",200L));
CountDownLatch latch = new CountDownLatch(taskList.size());
ConcurrentHashMap<String,String> results = new ConcurrentHashMap<>();
for (int i = 0; i < taskList.size(); i++) {
Task task = taskList.get(i);
new Thread(() -> {
try {
Thread.sleep(task.getTime());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
latch.countDown();
String threadName = Thread.currentThread().getName();
results.put(threadName,task.getName());
System.out.println(threadName+"完成加工:"+task.getName()+",耗时:"+task.getTime()+"毫秒");
},"线程"+(i+1)).start();
}
latch.await();
for (Map.Entry<String, String> entry : results.entrySet()) {
System.out.println("总部收到了来自"+entry.getKey()+"加工的"+entry.getValue());
}
if(results.size() == taskList.size()){
System.out.println("所有部件加工完成,可以组装电脑");
}
}
public static void main(String[] args) throws InterruptedException {
produce();
}
}
运行结果
makefile
线程5完成加工:电源,耗时:200毫秒
线程3完成加工:内存,耗时:500毫秒
线程2完成加工:主板,耗时:800毫秒
线程4完成加工:显卡,耗时:1000毫秒
线程1完成加工:CPU,耗时:2000毫秒
总部收到了来自线程4加工的显卡
总部收到了来自线程5加工的电源
总部收到了来自线程2加工的主板
总部收到了来自线程3加工的内存
总部收到了来自线程1加工的CPU
所有部件加工完成,可以组装电脑
其他使用场景
- 统计大屏页面数据时,把各个模块的数据使用多线程统计出来后,封装之后再一起返给前端。
- 文件处理时,同时启动多个线程分别处理不同的文件,多线程把所有文件处理完毕后,再进行汇总和分析。
- 系统启动时多线程加载配置文件、初始化数据库连接等操作,当这些操作完成后,业务处理线程才能开始工作。