大白话之 Java 多线程 join 方法:开局一张图,试学一分钟,你就费和我一样,理解介个方法

本贴最后更新于 2052 天前,其中的信息可能已经渤澥桑田

前言

有次偶尔接触到了 Thread.join() 方法,便到网上去查阅相关资料,但也是看得我一头雾水(天下文章一般抄)。在我很久的理解之后,便想将我理解的 join() 方法以一张图的方式解释出来。

要学习本篇文章,你需要理解以下知识:

仔细看

开局扔张图:

4260820190710.png

我绘制的这张图以时间线的形式解释了主线程和各个被实例化的 John 线程的运行过程。

别着急,多看两遍!

我们可以看到,在主线程调用了 join() 方法后,指定的线程会被抓回来在后边老老实实地排队。

猜一下

问:请回答未执行 join() 方法和执行了 join() 方法的运行结果有什么不同(可能有几种结果、运行的时间、输出的顺序)?

💡—!>

答:

类型 | 可能结果数量 | 运行速度 | 输出顺序 | 时间复杂度(最好)
---|---|---
不使用 join()|6 种 | 快(多线程)| 乱序 |O(1)
使用 join()|1 种 | 慢(单线程)| 顺序 |O(n)

Q&A

看完后,你可能还会有些疑问:

Q:为什么不使用 join() 的可能结果数量是 6 种?输出顺序为什么是乱序?
A:由于多线程的原因,虽然 start() 顺序执行了线程 1/2/3,但可能由于各种原因,某个线程会抢先完成,从而造成了 6 种运行结果 ——

123 132 213 231 321 312

多线程并不老实,并且难以(不是不可能)控制。

Q:为什么使用 join() 后会变慢?
A:因为使用 join() 后,三个线程会按顺序被赶到主线程去运行,这时候它们就不能够同时运行了,只能一个一个地运行。

自己做

别偷懒,打开你的 IDE,把下边的代码粘贴进去:

public class TestJoin { public static void main(String[] args) { John john1 = new John(); John john2 = new John(); John john3 = new John(); try { john1.start(); john1.join(); john2.start(); john2.join(); john3.start(); john3.join(); } catch (InterruptedException IE) { IE.printStackTrace(); } } } class John extends Thread { @Override public void run() { for (int i = 0; i < 2; i++) { try { Thread.sleep(500); System.out.println("Current Thread: " + Thread.currentThread().getName()); } catch(Exception ex) { System.out.println("Exception has" + " been caught" + ex); } System.out.println(i); } } }

运行结果:

Current Thread: Thread-0 0 Current Thread: Thread-0 1 Current Thread: Thread-1 0 Current Thread: Thread-1 1 Current Thread: Thread-2 0 Current Thread: Thread-2 1

可以看到,苦逼的三个线程都被拉到了主线程顺序执行。

现在,删掉两行代码:

john2.join(); john3.join();

再次运行:

Current Thread: Thread-0 0 Current Thread: Thread-0 1 Current Thread: Thread-1 0 Current Thread: Thread-2 0 Current Thread: Thread-2 1 Current Thread: Thread-1 1

可以看到,john2john3 两个线程并未在主线程中运行,所以运行结果也发挥得比较自由,且运行时间也缩短了。

此处请注意,在使用 join() 方法之前,一定要先使用 start() 方法启动线程。线程根本没工作,那还咋拉过去?

后语

到此,你已经掌握了 join() 方法的使用。不要问我能用来做什么,等到你需要它的功能时,你就不会再手忙脚乱了。

很认真,你读到了最后。让我们再来讲讲 yield() 方法吧(别的文章都讲了):

yield() 方法的作用,与 join() 方法无瓜。当你对一个线程执行 yield() 方法后,该线程会尝试暂停自己,给后面正在排队的同级线程让道(即拱手让人),它是一个不稳定的过程(不一定有效果,也不一定什么时候继续执行)。

另外,建议你趁着还能再学进点什么,再看看 syncronizedwait()notify() 这些有相似之处的知识比较好。

  • 大白话
    17 引用 • 27 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3198 引用 • 8215 回帖 • 1 关注
  • 知识讲解
    1 引用 • 1 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • someone
    作者

    没错,因为 yield() 的结束时间是无法准确预测的。