CountDownLatch线程计数器学习笔记

122 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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();
}