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

talk is cheap,show me the code and the result

1.先来一个好理解的:

下面这个例子中,由于子线程循环了100次,干的活多,走的慢,所以结束的晚。可以看到执行结果,主线程结束后,子线程稍等了一会才结束执行,并没有主线程需要等待子线程结束的情况。
主线程的任务:
1.thread.start 开启子线程
2.System.out.println(Thread.currentThread().getName()+“结束了 ,这是main干的活”); 输出语句
子线程的任务:

  1.            for (int i = 0; i < 100; i++) {if (i==99){System.out.println("我现在是99,这是子线程干的活");}}    //循环100次,并输出语句
    

也就是说,谁先完成任务,谁就会先运行结束。

public class ThreadOne {public static void main(String[] args) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 100; i++) {if (i==99){System.out.println("我现在是99,这是子线程干的活");}}}});thread.start();System.out.println(Thread.currentThread().getName()+"结束了 ,这是main干的活");}
}
输出结果:
main结束了 ,这是main干的活
我现在是99,这是子线程干的活

2.主线程通过方法调用开启子线程并执行任务

记得刚开始学这个的时候我也是迷惑的,为什么,主线程的方法,方法里的内容还没执行完,主线程就结束了呐,我是脸脸懵逼呀,其实,还是按照第一步中说的,看执行的任务,先上代码

public class Outter {public static void main(String[] args) throws InterruptedException {Outter outter = new Outter();int b = 10;int test = outter.test(b);//这里调用了方法并且在方法中开启了子线程,test()方法还没执行结束,为啥主线程就走完了呐System.out.println(test);System.out.println("main 结束了");}public int test(final int b) {final int a = 10;new Thread(){public void run() {System.out.println(a);System.out.println(b);};}.start();return 5555;}
}

多次运行后,执行结果如下:

那上面这个例子中,main线程的任务是什么,子线程的任务是什么:
主线程:
1.第一部分活(干活的意思)

        Outter outter = new Outter();int b = 10;int test = outter.test(b); //调用test方法System.out.println(test);System.out.println("main 结束了");

2.第二部分活

.start()开启子线程
final int a = 10;
return 5555;

子线程:

  System.out.println(a);System.out.println(b);

之前一直迷惑的是,主线程调用了test()方法,为啥这个方法没结束main线程就结束了呐,其实是因为主线程只需要调用了这个方法,并且返回一个返回值,主线程的任务就结束了,至于主线程创建的子线程,去干别的事情还需要多少时间,主线程是不关心的。
举个通俗的例子:周末我在家中玩lol,正玩着突然饿了(我是主线程),喊我女朋友去搞点吃的(调用吃东西方法,吃东西方法内部,开启女朋友线程[子线程]),我接着打lol,发现打完了,女朋友还没做好饭哈哈(手动god head),我去倒头睡了。我只是调用了吃东西方法,喊一下(调用后就结束了),女朋友啥时候做好饭我不管。。。

3.可以控制让子线程结束后,主线程再结束吗。。。

上面举得例子太不真实啦哈哈,我都飘了,不过也是为了帮助理解。实际情况中,主线程可能要等待子线程执行完,返回对应的结果,取道结果后,接下来主线程继续执行或者结束。打完游戏后,我需要等女朋友把饭拿过来吃了后,我才能饱饱得睡觉哈,饭不过来,我不能睡觉,也就是子线程结束前主线程不能结束。
那有没有什么方法呐?肯定是有的哈,Java的Thread类提供了join方法。
如果需要主线程等待子线程结束,只需要在主线程的任务中,用子线程对象调用join()方法即可。
这里就不再赘述了,引用别人写的一篇文件哈,比较全面的几种方式:
引用文章原文链接:主线程等待子线程执行完毕再执行解决办法


线程从启动到执行完毕,一般会有一些耗时操作,并不能像一般的程序语句,就能立马结束。如下代码:

package com.xxx.async;public class WaitThreadDone {  public static void main(String[] args) {        Thread t1 = new Thread(new Runnable() {                @Override          public void run() {             try {                   System.out.println("thread "+Thread.currentThread().getName()+" start to run.");                  Thread.sleep(2000);                 System.out.println("thread " + Thread.currentThread().getName() + " done.");              } catch (Exception e) {                 e.printStackTrace();                }           }       });             System.out.println("main start to run.");     t1.start();     System.out.println("main done."); }}

这是一个典型的线程耗时操作,默认情况下,线程t1它不会立马结束,因此执行结果就是:

我们希望主线程开始之后,等待子线程运行结束,主线程继续执行。

考虑子线程是一个耗时的阻塞操作,我们需要通过程序让子线程运行结束再执行主线程。这里给出如下几种解决办法:

①、t1.join()
②、while(t1.isAlive())
③、while(Thread.activeCount()>1)
④、CountDownLatch

下面来看看具体的实现:

第一种办法:t1.start();后面接上t1.join()代码,如下:

第二种办法:判断子线程是否还存活

第三种办法:判断活跃的线程是否大于1

第四种办法:通过同步工具类CountDownLatch实现

这种办法需要CountDownLatch对象侵入线程run()方法的代码中。最终执行结果和前面几种解决办法一致。

CountDownLatch通过await()方法阻塞主线程,等待其他线程运行结束,通过countDown()方法来释放锁,主线程开始执行。

总结:在这四种解决办法中,一、二两种办法需要知道线程的名字,当有很多线程同时执行的时候,有时候,我们是无法直观的知道每个线程的名字,这两个办法用的很少见。第四种办法在多线程的情况下也可以使用,就是需要设置CountDownLatch latch = new CountDownLatch(n),指定需要等待的线程数。第三种办法无需知道线程的名字和线程的数量,使用起来很直观。

Java多线程之----主线程会等待子线程结束再结束么,怎么让主线程等待子线程结束呐?相关推荐

  1. JAVA多线程执行,等待返回结果,再执行

    JAVA多线程执行,等待返回结果,再执行 1.实现callable接口 1)配置线程池 package com.neusoft.demo.server.config;import org.spring ...

  2. Java多线程(超详解)

    目录 1. 线程简介 1.1 程序 1.2 进程 1.3 线程 1.4 多线程 1.5 普通方法调用和多线程 2. 线程创建 2.1 继承Thread类 2.2 实现Runnable接口 2.3 实现 ...

  3. Java多线程超详解

    引言 随着计算机的配置越来越高,我们需要将进程进一步优化,细分为线程,充分提高图形化界面的多线程的开发.这就要求对线程的掌握很彻底. 那么话不多说,今天本帅将记录自己线程的学习. 程序,进程,线程的基 ...

  4. Java 多线程深入浅出

    首先关于Volatile修饰符: Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存.这样在任何时刻,两 ...

  5. Java多线程的同步机制(synchronized)

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个 ...

  6. java word转html 烟火,Java多线程制作烟花效果.doc

    Java多线程制作烟花效果 Java多线程应用实例: 制作烟花效果 本例知识点一句话讲解新学知识使用Thread类管理线程已学知识Math类产生随机数使用Color类设置颜色使用Graphics类绘制 ...

  7. Java多线程同步机制

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个 ...

  8. 【Java系列】(四)Java多线程---线程安全

    前言: 记得大一刚学Java的时候,老师带着我们做了一个局域网聊天室,用到了AWT.Socket.多线程.I/O,编写的客户端和服务器,当时做出来很兴奋,回学校给同学们演示,感觉自己好NB,呵呵,扯远 ...

  9. Java多线程技术~生产者和消费者问题

    Java多线程技术~生产者和消费者问题 本文是上一篇文章的后续,详情点击该连接 线程通信 应用场景:生产者和消费者问题 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取 ...

最新文章

  1. PyTorch Multi-GPU使用代码
  2. linux minicom usb串口
  3. 初学 Delphi 嵌入汇编[1] - 汇编语言与机器语言
  4. Django之路--第一篇
  5. 在cmd中使用python使用pip报错invalid syntax
  6. span 标记 width 设置
  7. 关于SDL SDL_CreateWindowFrom和SDL_DestroyWindow第二次后无法将视频显示出来。
  8. 从常识看中国经济社会-再续之续:套利
  9. 太吾绘卷第一世攻略_建平中学高二数学周练卷(2020.09)
  10. 自考本科计算机类专业查询,自考本科学位如何查询
  11. 触动精灵mysql用法_[触动精灵]触动精灵官方手册流水账2
  12. 如何使得OCX控件能响应PreTranslateMessage消息?
  13. mac java jni_Mac OS上编译JNI的动态库
  14. 基于MATLAB 关于圆的研究
  15. Leetcode452. 用最少数量的箭引爆气球(排序+贪心)
  16. linux 9 -- 交互式使用Bash Shell
  17. java p12证书,如何使用已安装的.p12 证书在 Mac OS X 上签名 jar?
  18. 烽火吉比特HG261GU获取超级密码教程
  19. Intel编译器安装WRF-CMAQ
  20. android渠道首发规则,酷传推广手册Android渠道首发规则.doc

热门文章

  1. saltstack之grains与pillar讲解(3)
  2. 如何使输入算术表达式时允许操作数和运算符之间加入任意多个空格符
  3. Android 设备,如何root,执行adb shell,查看设备中的数据库信息等
  4. Git 从远程拉取文件
  5. 三星I9100有时不能收发彩信完美解决!中国移动
  6. mysql 结果 临时表_mysql使用查询结果作为临时表
  7. Detours学习之十:用于查找目标函数的api
  8. Eolinker实用功能
  9. hive -e和hive -f的用法
  10. 【BZOJ4184】shallot(线段树分治,线性基)