文章目录

  • 1.Thread sleep()
  • 2.Thread join()
  • 3.synchronized 等待唤醒机制
  • 4.ExecutorService isTerminated() + while 轮询判断
  • 5.ExecutorService awaitTermination()
  • 6.Future
  • 7.CountDownLatch
  • 8.CyclicBarrier
  • 9.BlockingQueue
  • 10.CompletableFuture(本质还是Future的get方法)
  • 11.LockSupport(23.03.17更新)

提醒:
1 部分案例使用线程池创建线程。方便起见使用Executors.newFixedThreadPool()方法创建一个固定大小的线程池。
2 Runnable使用Lambda表达式创建
3 代码在main()方法中执行,出于方便演示,代码中有几处不规范的地方
4 JDK使用17版本

1.Thread sleep()

public static void main(String[] args) throws Exception {long timeout1 = 1000;long timeout2 = timeout1 + 500;new Thread(() -> {try {Thread.sleep(timeout1);} catch (InterruptedException e) {throw new RuntimeException(e);}}).start();// 满足 timeout2 > timeout1 即可Thread.sleep(timeout2);System.out.println("主线程执行!\ndo something...");
}

方法问题太多,不可取,仅作为参考

2.Thread join()

private static void test06() throws Exception {CopyOnWriteArrayList<Thread> list = new CopyOnWriteArrayList<>();for (int i = 0; i < 3; i++) {Thread thread = new Thread(() -> {try {// 随机生成睡眠时间long timeout = new Random().nextLong(1000, 3000);TimeUnit.MILLISECONDS.sleep(timeout);System.out.printf("%s 子线程执行完毕!耗时:%sms\n", Thread.currentThread().getName(), timeout);} catch (InterruptedException e) {throw new RuntimeException(e);}});list.add(thread);thread.start();}for (Thread thread : list) {thread.join();}System.out.println("主线程执行!\ndo something...");
}

3.synchronized 等待唤醒机制

public static void main(String[] args) throws Exception {Object lock = new Object();// 启动子线程new Thread(() -> {try {TimeUnit.SECONDS.sleep(1);System.out.println("子线程执行完毕");// 获取对象锁synchronized (lock) {// 子线程唤醒lock.notify();}} catch (InterruptedException e) {throw new RuntimeException(e);}}).start();synchronized (lock) {// 主线程等待lock.wait();}System.out.println("主线程执行!\ndo something...");
}

4.ExecutorService isTerminated() + while 轮询判断

思路:所有任务提交后,调用线程池的shutdown()方法,然后在死循环里每隔几秒调用一次线程池的isTerminated()方法,判断所有线程在线程池关闭后是否都已完成。需要注意的是调用isTerminated()前一定要先调用shutdown()或shutdownNow()方法,原因可以在isTerminated()的源码中找到,位于java.util.concurrent.ExecutorService 198行左右,内容如下:

翻译为中文:如果所有任务在关闭后都已完成,则返回 true。请注意,除非首先调用了 shutdown 或 shutdownNow,否则 isTerminated 永远不会为真。

实现代码:

public static void main(String[] args) throws Exception {int n = 3;String[] tasks = {"发送短信消息完毕", "发送微信消息完毕", "发送邮箱消息完毕"};int[] executeTimes = new int[]{2, 5, 1};ExecutorService threadPool = Executors.newFixedThreadPool(n);long start = System.currentTimeMillis();for (int i = 0; i < n; i++) {int finalI = i;threadPool.execute(() -> {try {TimeUnit.SECONDS.sleep(executeTimes[finalI]);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(tasks[finalI]);});}threadPool.shutdown();// 关键代码while (true) {if (threadPool.isTerminated()) {break;} else {// 每隔1s判断一次TimeUnit.SECONDS.sleep(1);}}System.out.println("所有消息都发送完毕了,执行主线程任务。\n耗时ms:" + (System.currentTimeMillis() - start));
}

缺点:若线程池中的任务完成耗时不确定,则不能及时执行主线程的任务

5.ExecutorService awaitTermination()

public static void main(String[] args) throws Exception {ExecutorService executorService = Executors.newFixedThreadPool(3);for (int i = 0; i < 3; i++) {executorService.execute(() -> {long timeout = new Random().nextLong(1000, 3000);try {TimeUnit.MILLISECONDS.sleep(timeout);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.printf("%s 子线程执行完毕!耗时:%sms\n", Thread.currentThread().getName(), timeout);});}executorService.shutdown();// 阻塞当前线程,直到所有已提交的任务完成执行,或者发生超时,或者当前线程中断,以先发生者为准。executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);System.out.println("主线程执行!\ndo something...");
}

6.Future

private static void test03() throws Exception{ExecutorService executorService = Executors.newFixedThreadPool(1);Future<String> future = executorService.submit(() -> {try {System.out.println("do something...");TimeUnit.SECONDS.sleep(1);System.out.println("子线程任务完成");} catch (InterruptedException e) {throw new RuntimeException(e);}return "子线程返回的结果";});System.out.println(future.get());executorService.shutdown();System.out.println("主线程执行!");
}

7.CountDownLatch

public static void main(String[] args) throws Exception {int n = 3;String[] tasks = {"发短信完毕", "发微信完毕", "发QQ完毕"};int[] executeTimes = new int[]{2, 5, 1};CountDownLatch countDownLatch = new CountDownLatch(n);ExecutorService executorService = Executors.newFixedThreadPool(n);long start = System.currentTimeMillis();for (int i = 0; i < n; i++) {int finalI = i;executorService.submit(() -> {try {TimeUnit.SECONDS.sleep(executeTimes[finalI]);System.out.println(tasks[finalI]);} catch (InterruptedException e) {e.printStackTrace();} finally {countDownLatch.countDown();}});}countDownLatch.await();System.out.println("所有消息都发送完毕了,执行主线程任务。\n耗时ms:" + (System.currentTimeMillis() - start));// 不要忘记关闭线程池,不然会导致主线程阻塞无法退出executorService.shutdown();
}

8.CyclicBarrier

private static void test07() throws Exception{CyclicBarrier cyclicBarrier = new CyclicBarrier(6);// 最后一个达到屏障的线程留给主线程,因此循环5次for (int i = 0; i < 5; i++) {new Thread(() -> {long timeout = new Random().nextLong(1000, 3000);try {TimeUnit.MILLISECONDS.sleep(timeout);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.printf("%s 子线程执行完毕!耗时:%sms\n", Thread.currentThread().getName(), timeout);// 到达屏障try {cyclicBarrier.await();} catch (InterruptedException e) {throw new RuntimeException(e);} catch (BrokenBarrierException e) {throw new RuntimeException(e);}}).start();}cyclicBarrier.await();System.out.println("主线程执行!\ndo something...");
}

9.BlockingQueue

public static void main(String[] args) throws Exception {BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);new Thread(() -> {try {TimeUnit.SECONDS.sleep(1);queue.put("OK");} catch (InterruptedException e) {e.printStackTrace();}}).start();System.out.println(queue.take());System.out.println("主线程执行!\ndo something...");
}

10.CompletableFuture(本质还是Future的get方法)

public static void main(String[] args) throws Exception {CompletableFuture<Void> cf1 = CompletableFuture.runAsync(() -> {try {TimeUnit.SECONDS.sleep(1);System.out.println("cf1 任务完成");} catch (InterruptedException e) {throw new RuntimeException(e);}});CompletableFuture<Void> cf2 = CompletableFuture.runAsync(() -> {try {TimeUnit.SECONDS.sleep(2);System.out.println("cf2 任务完成");} catch (InterruptedException e) {throw new RuntimeException(e);}});CompletableFuture<Void> cf3 = CompletableFuture.runAsync(() -> {try {TimeUnit.SECONDS.sleep(0);System.out.println("cf3 任务完成");// int n = 1 / 0;} catch (InterruptedException e) {throw new RuntimeException(e);}});CompletableFuture<Void> allOf = CompletableFuture.allOf(cf1, cf2, cf3);// 若子任务都未发生异常则返回null,否则返回异常。此步会阻塞主线程System.out.println(allOf.get());System.out.println("主线程执行!");
}

11.LockSupport(23.03.17更新)

public static void main(String[] args) {Thread mainThread = Thread.currentThread();new Thread(() -> {try {System.out.println("子线程开始执行");// 模拟子线程执行任务TimeUnit.SECONDS.sleep(2);System.out.println("子线程执行完毕!");} catch (InterruptedException e) {throw new RuntimeException(e);}// 如果线程在 park 上被阻塞,那么它将解除阻塞LockSupport.unpark(mainThread);}).start();// 禁用当前线程(主线程)LockSupport.park();System.out.println("主线程执行!\ndo something...");
}

【Java并发编程】主线程等待子线程的多种方法相关推荐

  1. java等待5秒_Java并发编程-主线程等待子线程解决方案

    主线程等待所有子线程执行完成之后,再继续往下执行的解决方案 public class TestThread extends Thread { public void run() { System.ou ...

  2. VC++ 中主线程等待子线程结束的方法

    void WaitForThreadExit(void) {DWORD dwRet; //返回值MSG msg; int wait_count=4; //线程句柄有4个int nExitThreadC ...

  3. Java并发编程原理与实战六:主线程等待子线程解决方案

    Java并发编程原理与实战六:主线程等待子线程解决方案 参考文章: (1)Java并发编程原理与实战六:主线程等待子线程解决方案 (2)https://www.cnblogs.com/pony1223 ...

  4. java 主线程等待_Java实现主线程等待子线程

    本文介绍两种主线程等待子线程的实现方式,以5个子线程来说明: 1.使用Thread的join()方法,join()方法会阻塞主线程继续向下执行. 2.使用Java.util.concurrent中的C ...

  5. Java多线程之----主线程会等待子线程结束再结束么,怎么让主线程等待子线程结束呐?

    首先给出结论: 主线程和子线程之间没有谁先谁后结束这种关联,它们只是各自负责自己的线程任务,如果该线程的任务结束了,该线程自然会结束运行. talk is cheap,show me the code ...

  6. 如何实现java主线程等待子线程执行完毕之后再执行?

    本文转自:问题:如何实现java主线程等待子线程执行完毕之后再执行? - jseven - 博客园 点击关注强哥,查看更多精彩文章呀 工作总往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完 ...

  7. 【多线程】学习记录七种主线程等待子线程结束之后在执行的方法

    最近遇到一个问题需要主线程等待所有的子线程结束,才能开始执行,统计所有的子线程执行结果,返回,网上翻阅各种资料,最后记录一下,找到七种方案 第一种:while循环 对于"等待所有的子线程结束 ...

  8. c++主线程等待子线程结束_简单明了的 Python 多线程来了 | 原力计划

    作者 | 万里羊责编 | 王晓曼出品 | CSDN博客线程和进程计算机的核心是CPU,它承担了所有的计算任务,就像是一座工厂在时刻运行.如果工厂的资源有限,一次只能供一个车间来使用,也就是说当一个车间 ...

  9. Java主线程等待子线程、线程池

    public class TestThread extends Thread { public void run() { System.out.println(this.getName() + &qu ...

最新文章

  1. 蓝桥杯【介绍】和【如何准备才可以拿奖】
  2. .NET语言的编译过程:中间语言(IL)和即时编译器(JIT)
  3. how drop down list description is displayed by UI framework
  4. 剑指offer之求两个链表的第一个公共节点
  5. 快手上的cosplay大师有多野?
  6. 1. JanusGraph的优势
  7. 1052. 卖个萌 (20)-PAT乙级真题
  8. pip可识别的requirements.txt的写法
  9. Android MD5加密
  10. 微信卡券开发错误自排查参考文档
  11. 上座部佛教的佛陀略传
  12. [USACO题库]1.2.3 Name That Number命名那个数字
  13. 【UE4】给制作的小地图加上方向指针
  14. au能否打开m4a文件_什么是M4V文件(以及如何打开一个文件)?
  15. ncm 网络_HS-NCM超高速网卡
  16. Kooboo CMS - 之后台注册用户流程方法。
  17. Windows 程式设计书籍
  18. 2022 腾讯社招Golang后端面试经验分享
  19. RK3399学习笔记 1.0.3---python环境 Firefly Core-3399pro-jd4 Win10上RKNN工具安装
  20. python中找最小值,使用循环python查找最小值

热门文章

  1. 【引语练习题】直接引语为疑问句转为间接引语时注意
  2. Nexus 6 编译并刷机 Android 7.1.1 AOSP以及常用的修改源码快速验证方法
  3. android6.0升级名单,一加公布Android 6.0升级名单 一加X还要再等等
  4. linux 内核 strftime,linux 下时间函数strftime()的用法
  5. 大学数学小屋闲题002-洛必达法则证明
  6. nginx proxy_redirect 作用
  7. Texmaker、texstudio 中无法输入中文
  8. canvas实现图片压缩
  9. 为什么python注释不能中文_python注释中文
  10. 不知道怎么向女神表白?Python三大神技分分钟带你成功逆袭!