一个主线程等待多个子线程都执行完成后,才能继续执行的场景
适用于框架启动前,进行多项初始化工作等场景:多项初始化工作都完成后,才能开始启动框架处理。
或者用于统计多个线程是否都已执行完成:kafka消费者多线程执行消费,多个子线程并行执行,只有当子线程都执行完成后,才能提交offset
- package com.autoee.demo.javabase.mutiThread.CountDownLatch;
-
- import cn.hutool.core.thread.ThreadUtil;
- import cn.hutool.core.util.RandomUtil;
- import lombok.SneakyThrows;
-
- import java.util.concurrent.CountDownLatch;
-
- /**
- * Title:
- * Desc:
- * Date: 2022-8-26
- * @author Double
- * @version 1.0.0
- */
- public class CountDownLatchTest1 {
-
- // CountDownLatch主要用来解决:
- // 一个主线程等待多个子线程都执行完成后,才能继续执行的场景
- // 适用于框架启动前,进行多项初始化工作等场景:多项初始化工作都完成后,才能开始启动框架处理。
- // 或者用于统计多个线程是否都已执行完成:kafka消费者多线程执行消费,多个子线程并行执行,只有当子线程都执行完成后,才能提交offset
- public static void main(String[] args) throws InterruptedException {
- // CountDownLatch中的个数要和实际执行的子线程数一致,否则执行过程就混乱了。
- int threadCount = 5;
- CountDownLatch tCountDownLatch = new CountDownLatch(threadCount);
-
- for (int i = 0; i < threadCount; i++) {
- new Thread("thread" + i) {
- @Override
- public void run() {
- String name = Thread.currentThread().getName();
- ThreadUtil.sleep(RandomUtil.randomInt(100) * 100);
- System.out.println("子线程" + name + "执行完成。");
-
- // 当前子线程执行完成,减1
- tCountDownLatch.countDown();
- }
- }.start();
-
- }
-
- // 阻塞等待上面的多个线程都执行完成
- tCountDownLatch.await();
-
- System.out.println("上面的子线程都已执行完成,主线程开始后续处理。。。");
-
- }
-
- }
子线程thread3执行完成。
子线程thread0执行完成。
子线程thread2执行完成。
子线程thread4执行完成。
子线程thread1执行完成。
上面的子线程都已执行完成,主线程开始后续处理。。。
多个线程并行执行多个阶段的任务,第1阶段任务所有子线程都执行完成后,所有子线程再开始第2阶段的任务, 第2阶段任务所有子线程都执行完成后,再进入下一阶段任务... 每个阶段所有子线程都执行完成后,主线程还可以执行一次该阶段的汇总任务。
- package com.autoee.demo.javabase.mutiThread.CyclicBarrier;
-
- import cn.hutool.core.thread.ThreadUtil;
- import lombok.SneakyThrows;
-
- import java.util.concurrent.BrokenBarrierException;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.CountDownLatch;
- import java.util.concurrent.CyclicBarrier;
-
- /**
- * Title:
- * Desc:
- * Date: 2022-8-26
- * @author Double
- * @version 1.0.0
- */
- public class CyclicBarrierTest1 {
-
- // CyclicBarrier主要用于:
- // 多个线程并行执行多个阶段的任务,第1阶段任务所有子线程都执行完成后,所有子线程再开始第2阶段的任务,
- // 第2阶段任务所有子线程都执行完成后,再进入下一阶段任务...
- // 每个阶段所有子线程都执行完成后,主线程还可以执行一次该阶段的汇总任务。
- public static void main(String[] args) {
-
- // 存放每阶段所有子线程的执行结果
- ConcurrentHashMap
resultMap = new ConcurrentHashMap(); -
- // CyclicBarrier中的parties要和实际执行的子线程数一致,否则执行过程就混乱了。
- int threadCount = 3;
-
- // 创建CyclicBarrier,并定义每阶段执行完成后的汇总任务
- CyclicBarrier tCyclicBarrier = new CyclicBarrier(threadCount, new Runnable() {
- @Override
- public void run() {
- long id = Thread.currentThread().getId();
- System.out.println("【开始】-每个阶段任务所有子线程都执行完成后-汇总线程" + id + "开始-当前阶段的汇总任务...");
- resultMap.forEach((k, v) -> {
- System.out.println("----------[获取]-" + v);
- });
- System.out.println("【完成】-每个阶段任务所有子线程都执行完成后-汇总线程" + id + "完成-当前阶段的汇总任务...");
- }
- });
-
- // 创建多个子线程,并发执行每个阶段的任务
- for (int i = 0; i < threadCount; i++) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- long id = Thread.currentThread().getId();
- String name = Thread.currentThread().getName();
- System.out.println("[开始]-" + name + "-第1阶段任务...");
- ThreadUtil.sleep(1000 + id);
- System.out.println("[完成]-" + name + "-第1阶段任务...");
-
- // 将子线程当前阶段的执行结果放入resultMap,key为线程名称
- resultMap.put(name, "子线程-" + name + "-第1阶段-sleep时间=" + (1000 + id));
- try {
- // 所有子线程等待其他子线程完成第一阶段任务,等都完成后,再进入下一阶段
- tCyclicBarrier.await();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- System.out.println("[开始]-" + name + "-第2阶段任务...");
- ThreadUtil.sleep(1000 + id);
- System.out.println("[完成]-" + name + "-第2阶段任务...");
-
- // 将子线程当前阶段的执行结果放入resultMap,key为线程名称,覆盖上一阶段的执行结果
- resultMap.put(name, "子线程-" + name + "-第2阶段-sleep时间=" + (1000 + id));
- try {
- // 所有子线程等待其他子线程完成第一阶段任务,等都完成后,再进入下一阶段
- tCyclicBarrier.await();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
- }, "线程" + (i + 1)).start();
- }
-
- System.out.println("上面的子线程不会阻塞当前主线程的执行");
- }
- }
上面的子线程不会阻塞当前主线程的执行
[开始]-线程3-第1阶段任务...
[开始]-线程2-第1阶段任务...
[开始]-线程1-第1阶段任务...
[完成]-线程1-第1阶段任务...
[完成]-线程2-第1阶段任务...
[完成]-线程3-第1阶段任务...
【开始】-每个阶段任务所有子线程都执行完成后-汇总线程14开始-当前阶段的汇总任务...
----------[获取]-子线程-线程2-第1阶段-sleep时间=1013
----------[获取]-子线程-线程3-第1阶段-sleep时间=1014
----------[获取]-子线程-线程1-第1阶段-sleep时间=1012
【完成】-每个阶段任务所有子线程都执行完成后-汇总线程14完成-当前阶段的汇总任务...
[开始]-线程3-第2阶段任务...
[开始]-线程1-第2阶段任务...
[开始]-线程2-第2阶段任务...
[完成]-线程1-第2阶段任务...
[完成]-线程2-第2阶段任务...
[完成]-线程3-第2阶段任务...
【开始】-每个阶段任务所有子线程都执行完成后-汇总线程14开始-当前阶段的汇总任务...
----------[获取]-子线程-线程2-第2阶段-sleep时间=1013
----------[获取]-子线程-线程3-第2阶段-sleep时间=1014
----------[获取]-子线程-线程1-第2阶段-sleep时间=1012
【完成】-每个阶段任务所有子线程都执行完成后-汇总线程14完成-当前阶段的汇总任务...