开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
CountDownLatch类位于 java.util.concurrent 包下,一个线程等待其他线程各自执行完毕后再执行。 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
CountDownLatch主要方法有
//阻塞并等待计算归零,直到`latch`的值被减到`0`或者当前线程被中断,当前线程就会被唤醒。
public void await();
//阻塞一段时间,并等待计算归零,如果超时就停止阻塞
public boolean await(long timeout, TimeUnit unit);
//使`latch`的值减`1`,如果减到了`0`,则会唤醒所有等待在这个`latch`上的线程。
public void countDown();
//获得`latch`的数值。
public void getCount();
CountDownLatch使用
1、主线程等待子线程执行完在执行:
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(()->{
try {
Thread.sleep(1000);
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
new Thread(()->{
try {
Thread.sleep(1000);
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"B").start();
System.out.println("主线程等待子线程执行完毕");
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程执行完毕");
2、创建异步线程执行类,导入大批量数据
@Service
@Slf4j
public class AsyncServiceImpl implements AsyncService {
@Override
@Async("asyncServiceExecutor")
public void executeAsync(List<LogOutputResult> logOutputResults, LogOutputResultMapper logOutputResultMapper, CountDownLatch countDownLatch) {
try{
log.warn("start executeAsync");
//异步线程要做的事情
logOutputResultMapper.addLogOutputResultBatch(logOutputResults);
log.warn("end executeAsync");
}finally {
// 很关键, 无论上面程序是否异常必须执行countDown,否则await无法释放
countDownLatch.countDown();
}
}
}
@Override
public int testMultiThread() {
List<LogOutputResult> logOutputResults = getTestData();
//测试每1000条数据插入开一个线程
List<List<LogOutputResult>> lists = ConvertHandler.splitList(logOutputResults, 1000);
CountDownLatch countDownLatch = new CountDownLatch(lists.size());
for (List<LogOutputResult> listSub:lists) {
asyncService.executeAsync(listSub, logOutputResultMapper,countDownLatch);
}
try {
//保证之前的所有的线程都执行完成,才会走下面的
// 这样就可以在下面拿到所有线程执行完的集合结果
countDownLatch.await();
} catch (Exception e) {
log.error("阻塞异常:"+e.getMessage());
}
return logOutputResults.size();
}