为什么80%的码农都做不了架构师?>>>
前言
上一篇博文说到semaphore,一个加强版的synchronized,该多线程辅助工具适用于控制对资源操作或者访问的场景。现在有一张场景是,需要等各个线程都都执行完了再进行下一步的操作,比如需要批量对上传的文件进行压缩,上传十个文件,压缩成一个包,这时候,就需要等上传完十个以后再进行压缩操作,类似于阻塞,concurrent包提供了countdownLatch辅助工具。
countdownLatch,中文翻译是门闩的意思,类似一个计数器,控制线程执行任务的时机,以组团的方式一起执行任务。该类会判断count计数不为0时,则呈wait状态,也就是屏障处等待,如果为0则继续执行。
入门
开启两个线程进行计数,同时主线程在wait状态,最后实现组团执行后续任务:
@Testpublic void testCountDownLatch() throws InterruptedException {CountDownLatch latch = new CountDownLatch(2);for (int i = 0; i < 2; i++) {new Thread(() -> {log.info("开始count,当前是线程:{},时间是:{}",Thread.currentThread().getName(),LocalDateTime.now());try {Thread.currentThread().sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}latch.countDown();}).start();}log.info("等待计数器count,现在是:{}", LocalDateTime.now());latch.await();log.info("结束计数器count,现在是:{}", LocalDateTime.now());}
运行结果是:
比较复杂的使用案例
模拟运动员从到场准备到开跑的过程,具体代码如下:
@Test public void testCountDownLatch2() throws InterruptedException {CountDownLatch comingTag = new CountDownLatch(5);CountDownLatch waitTag = new CountDownLatch(1);CountDownLatch waitRunTag = new CountDownLatch(5);CountDownLatch beginTag = new CountDownLatch(1);CountDownLatch endTag = new CountDownLatch(5);for (int i = 0; i < 5; i++) {new Thread(() -> {try {Thread.sleep(5000);log.info("{}号运动员已经入场,time:{}", Thread.currentThread().getName(), LocalDateTime.now());comingTag.countDown();waitTag.await();log.info("{}号运动员开始准备,time:{}", Thread.currentThread().getName(), LocalDateTime.now());Thread.sleep(3000);waitRunTag.countDown();log.info("{}号运动员准备结束,time:{}", Thread.currentThread().getName(), LocalDateTime.now());beginTag.await();log.info("{}号运动员开跑,time:{}", Thread.currentThread().getName(), LocalDateTime.now());Thread.sleep(2000);log.info("{}号运动员跑完了,time:{}", Thread.currentThread().getName(), LocalDateTime.now());endTag.countDown();} catch (InterruptedException e) {e.printStackTrace();}}).start();}comingTag.await();log.info("运动员全部入场,time:{}", LocalDateTime.now());log.info("预备口令,time:{}", LocalDateTime.now());Thread.sleep(2000);waitTag.countDown();waitRunTag.await();log.info("远动员准备完毕,time:{}", LocalDateTime.now());log.info("发令枪响,time:{}", LocalDateTime.now());Thread.sleep(2000);beginTag.countDown();endTag.await();log.info("全部运动员到达终点,time:{}", LocalDateTime.now()); }
运行结果是: