前言
CountDownLatch:CountDown英文解释为倒数,Latch是锁上,门闩的意思。在开发时,当我们有三个并发任务同时去执行,然后在下一步需要等待它们都执行完成才能继续执行,实现这个现在想想大概有几种方式,Thread.join等待线程,使用wait()notify(),Executor.invokeAll、然后对各个Future调用get等。而我们的CountDownLatch类就是专门用来控制这种情况的。初始化的时候创建一个倒计时次数count,通过调用countDown()方法对count的次数进行减1,当count次数为0的时候,调用await()的等待的线程会被释放。
代码
创建线程池
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ThreadPoolTask {
"taskExecutor") (
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutor-");
//线程池对拒绝任务的处理策略:这里采用了CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}定义线程
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TaskTest {
"taskExecutor") (
public void doTask(CountDownLatch count) throws Exception {
int num = RandomUtils.nextInt()
log.info("开始做任务:{}",num);
long start = System.currentTimeMillis();
Thread.sleep(num);
long end = System.currentTimeMillis();
count.countDown();
log.info("完成任务{},耗时:{}毫秒",num,(end - start));
}
}测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21(SpringJUnit4ClassRunner.class)
public class ApplicationTests {
private TaskTest task;
public void test() throws Exception {
int runnerCount = 10;
//初始化计数次数。
CountDownLatch count = new CountDownLatch(runnerCount);
log.info("线程池开始");
for (int i = 0; i < runnerCount; i++) {
task.doTask(count);
}
//只有当task中所有的任务完成了,await方法才会被释放,不然会一直阻塞。
//当然也可以使用他的超时方法count.await(5, TimeUnit.SECONDS);当所有线程任务的执行完成时间,超过5分钟的时候,会超时释放。
count.await();
log.info("线程池结束");
}
}
总结
CountDownLatch使用起来还是很简单的。在需要知道其他线程任务已经完成,才能继续执行的方法中有很大的作用。