场景:

  1. package com.java4all.mypoint;
  2.  
  3. import java.util.concurrent.CountDownLatch;
  4.  
  5. public class ThreadTest {
  6.  
  7. public static void main(String[] args)throws Exception{
  8. System.out.println("主线程正在执行前:"+Thread.currentThread().getName());
  9. test3();
  10. System.out.println("主线程正在执行后:"+Thread.currentThread().getName());
  11. }
  12.  
  13. public static void test3(){
  14. try {
  15. for (int i = 1 ;i <= 10;i ++){
  16. Thread.sleep(1000);
  17. new Thread(()->{
  18. System.out.println("子线程正在执行:"+Thread.currentThread().getName());
  19. }).start();
  20. }
  21. }catch (Exception ex){
  22. ex.printStackTrace();
  23. }
  24. }
  25.  
  26. }

  执行结果为:

  1. 主线程正在执行前:main
  2. 子线程正在执行:Thread-0
  3. 子线程正在执行:Thread-1
  4. 子线程正在执行:Thread-2
  5. 子线程正在执行:Thread-3
  6. 子线程正在执行:Thread-4
  7. 子线程正在执行:Thread-5
  8. 子线程正在执行:Thread-6
  9. 子线程正在执行:Thread-7
  10. 子线程正在执行:Thread-8
  11. 主线程正在执行后:main
  12. 子线程正在执行:Thread-9

  

可以看到,子线程还没执行完时,主线程进来了。

1.使用CountDownLatch

示例如下,我们初始化一个CountDownLatch,值为10(子线程个数),然后每次一个子线程执行完后执行一下countDown(),代码示例如下:

  1. package com.java4all.mypoint;
  2.  
  3. import java.util.concurrent.CountDownLatch;
  4. import java.util.concurrent.TimeUnit;
  5.  
  6. public class ThreadTest {
  7.  
  8. /**初始化CountDownLatch,值为线程数量*/
  9. private static final CountDownLatch ctl = new CountDownLatch(10);
  10.  
  11. public static void main(String[] args)throws Exception{
  12. System.out.println("主线程正在执行前:"+Thread.currentThread().getName());
  13. test3();
  14. ctl.await(20, TimeUnit.SECONDS);//最多等待20秒,不管子线程完没完
  15. System.out.println("主线程正在执行后:"+Thread.currentThread().getName());
  16. }
  17.  
  18. public static void test3(){
  19. try {
  20. for (int i = 1 ;i <= 10;i ++){
  21. Thread.sleep(1000);
  22. new Thread(()->{
  23. System.out.println("子线程正在执行:"+Thread.currentThread().getName());
  24. }).start();
  25. ctl.countDown();
  26. }
  27. }catch (Exception ex){
  28. ex.printStackTrace();
  29. }
  30. }
  31.  
  32. }

  执行结果为:

  1. 主线程正在执行前:main
  2. 子线程正在执行:Thread-0
  3. 子线程正在执行:Thread-1
  4. 子线程正在执行:Thread-2
  5. 子线程正在执行:Thread-3
  6. 子线程正在执行:Thread-4
  7. 子线程正在执行:Thread-5
  8. 子线程正在执行:Thread-6
  9. 子线程正在执行:Thread-7
  10. 子线程正在执行:Thread-8
  11. 子线程正在执行:Thread-9
  12. 主线程正在执行后:main

  

java8之前的方式写:

线程类:
  1. package com.java4all.mypoint;
  2.  
  3. import java.util.concurrent.CountDownLatch;
  4.  
  5. /**
  6. * Author: yunqing
  7. * Date: 2018/7/23
  8. * Description:
  9. */
  10. public class MyRunnable implements Runnable{
  11.  
  12. public CountDownLatch countDownLatch;
  13.  
  14. @Override
  15. public void run() {
  16. try {
  17. Thread.sleep(2000);
  18. System.out.println("子线程正在执行任务,当前线程为:"+Thread.currentThread().getName());
  19. }catch (InterruptedException inex){
  20. inex.printStackTrace();
  21. }finally {
  22. countDownLatch.countDown();
  23. }
  24. }
  25.  
  26. public CountDownLatch getCountDownLatch() {
  27. return countDownLatch;
  28. }
  29.  
  30. public void setCountDownLatch(CountDownLatch countDownLatch) {
  31. this.countDownLatch = countDownLatch;
  32. }
  33. }

  

测试类:
  1. package com.java4all.mypoint;
  2.  
  3. import java.util.concurrent.CountDownLatch;
  4. import java.util.concurrent.TimeUnit;
  5.  
  6. public class ThreadTest {
  7.  
  8. /**初始化CountDownLatch,值为线程数量*/
  9. private static final CountDownLatch ctl = new CountDownLatch(10);
  10.  
  11. public static void main(String[] args)throws Exception{
  12. System.out.println("主线程正在执行前:"+Thread.currentThread().getName());
  13. for(int i = 1;i <= 10;i ++){
  14. MyRunnable runnable = new MyRunnable();
  15. runnable.setCountDownLatch(ctl);
  16. Thread thread = new Thread(runnable);
  17.  
  18. thread.start();
  19. }
  20. ctl.await(20, TimeUnit.SECONDS);//最多等待20秒,不管子线程完没完
  21. System.out.println("主线程正在执行后:"+Thread.currentThread().getName());
  22. }
  23.  
  24. }

  

结果为:
  1. 主线程正在执行前:main
  2. 子线程正在执行任务,当前线程为:Thread-1
  3. 子线程正在执行任务,当前线程为:Thread-0
  4. 子线程正在执行任务,当前线程为:Thread-2
  5. 子线程正在执行任务,当前线程为:Thread-3
  6. 子线程正在执行任务,当前线程为:Thread-4
  7. 子线程正在执行任务,当前线程为:Thread-7
  8. 子线程正在执行任务,当前线程为:Thread-6
  9. 子线程正在执行任务,当前线程为:Thread-5
  10. 子线程正在执行任务,当前线程为:Thread-9
  11. 子线程正在执行任务,当前线程为:Thread-8
  12. 主线程正在执行后:main

  

附: 开启一个线程的其他写法:

  1. /**jdk7匿名内部类的写法*/
  2. public static void test1(){
  3. new Thread(new Runnable() {
  4. @Override
  5. public void run() {
  6. System.out.println("aaaa");
  7. }
  8. }).start();
  9. }
  10.  
  11. /**
  12. * jdk8
  13. * Runnable是个函数接口,可以利用jdk8的lambda来简写
  14. * 函数接口:是指内部只有一个抽象方法的接口
  15. * */
  16. public static void test2(){
  17. new Thread(()->{
  18. System.out.println("bbb");
  19. }).start();
  20. }

  

JAVA中等待所有线程都执行结束(转2)的更多相关文章

  1. java中等待所有线程都执行结束(转)

    转自:http://blog.csdn.net/liweisnake/article/details/12966761 今天看到一篇文章,是关于java中如何等待所有线程都执行结束,文章总结得很好,原 ...

  2. java中等待所有线程都执行结束

    转自:http://blog.csdn.net/liweisnake/article/details/12966761 今天看到一篇文章,是关于java中如何等待所有线程都执行结束,文章总结得很好,原 ...

  3. Java中如何保证线程顺序执行

    只要了解过多线程,我们就知道线程开始的顺序跟执行的顺序是不一样的.如果只是创建三个线程然后执行,最后的执行顺序是不可预期的.这是因为在创建完线程之后,线程执行的开始时间取决于CPU何时分配时间片,线程 ...

  4. 【java】【多线程】等待开启的多个线程都执行完成,再做事情,怎么实现

    今天在controller中写一个接口用来测试模拟多个请求同时到达 下订单的情况, 怎么能有效保证高并发下的库存和销量的一致性呢?[具体实现方法:https://www.cnblogs.com/sxd ...

  5. Java中的守护线程 & 非守护线程(简介)

    Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...

  6. Java 中如何实现线程间通信

    世界以痛吻我,要我报之以歌 -- 泰戈尔<飞鸟集> 虽然通常每个子线程只需要完成自己的任务,但是有时我们希望多个线程一起工作来完成一个任务,这就涉及到线程间通信. 关于线程间通信本文涉及到 ...

  7. Java中的守护线程和非守护线程(转载)

    <什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...

  8. 详解线程池的作用及Java中如何使用线程池

    服务端应用程序(如数据库和 Web 服务器)需要处理来自客户端的高并发.耗时较短的请求任务,所以频繁的创建处理这些请求的所需要的线程就是一个非常消耗资源的操作.常规的方法是针对一个新的请求创建一个新线 ...

  9. 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法

    [源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...

随机推荐

  1. zabbix忘记登录密码重置方法

    1.忘记zabbix之后,先用mysql查看一下: [root@centos7-106 ~]# mysql -uroot -p -e "select * from zabbix.users\ ...

  2. django-ckeditor表情包修改

    一.版本 Django==1.11 django-ckeditor==5.2.2 二.关键步骤 1.删除旧的ckeditor静态文件 所在目录:项目目录下的static文件夹下的ckditor文件夹 ...

  3. ASP.NET Core Web API + Angular 仿B站(一) 目的分析以及创建 WebAPI + Angular7 项目

    前言: 本系列文章主要为对所学 Angular 框架的一次微小的实践,对 b站页面作简单的模仿. 本系列文章主要参考资料: 微软文档: https://docs.microsoft.com/zh-cn ...

  4. 786. K-th Smallest Prime Fraction

    A sorted list A contains 1, plus some number of primes.  Then, for every p < q in the list, we co ...

  5. 51nod 1119【杨辉三角】

    思路: = =杨辉三角的应用,组合数的应用: C(N+M,N); 逆元一发,费马小定理,OK. #include <stdio.h> #include <string.h> # ...

  6. U3D 的一些基础优化

    1.在使用数组或ArrayList对象时应当注意 [csharp] view plaincopy length=myArray.Length; for(int i=0;i<length;i++) ...

  7. ubuntu 18 安装virtulenv以及virtualenvwrapper

    转自: https://www.jianshu.com/p/06533f19c4ad 首先安装pip,如果用的python3版本要安装pip3(自行google) sudo apt install v ...

  8. 同一台服务器上部署多个Tomcat的配置修改方法

    同一服务器部署多个tomcat时,存在端口号冲突的问题,所以需要修改tomcat配置文件server.xml,以tomcat7为例. 首先了解下tomcat的几个主要端口: <Server po ...

  9. 线段树(单点更新)/树状数组 HDOJ 1166 敌兵布阵

    题目传送门 /* 线段树基本功能:区间值的和,修改某个值 */ #include <cstdio> #include <cstring> #define lson l, m, ...

  10. LVS集群-DR模式

    同上个实验一样,还是准备三台机器 分发器(sishen_63):eth0 192.168.1.63 RealServer1sishen_64) RealServer2sishen_65) 首先配置网卡 ...