java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
join() 定义在 Thread.java 中,下文通过源码分享 join(), 需要的朋友参考下吧
join() 介绍join() 定义在 Thread.java 中。
join() 的作用:让" 主线程 "等待" 子线程 " 结束之后才能继续运行。这句话可能有点晦涩,我们还是通过例子去理解:
- // 主线程
- public class Father extends Thread {
- public void run() {
- Son s = new Son();
- s.start();
- s.join();
- ...
- }
- }
- // 子线程
- public class Son extends Thread {
- public void run() {
- ...
- }
- }
说明:
上面的有两个类 Father(主线程类) 和 Son(子线程类)。因为 Son 是在 Father 中创建并启动的,所以,Father 是主线程类,Son 是子线程类。
在 Father 主线程中,通过 new Son() 新建" 子线程 s"。接着通过 s.start() 启动 "子线程 s",并且调用 s.join()。在调用 s.join() 之后,Father 主线程会一直等待,直到 "子线程 s" 运行完毕;在 "子线程 s" 运行完毕之后,Father 主线程才能接着运行。 这也就是我们所说的 "join() 的作用,是让主线程会等待子线程结束之后才能继续运行 "!
join() 源码分析 (基于 JDK1.7.0_40)
- public final void join() throws InterruptedException {
- join(0);
- }
- public final synchronized void join(long millis) throws InterruptedException {
- long base = System.currentTimeMillis();
- long now = 0;
- if (millis < 0) {
- throw new IllegalArgumentException("timeout value is negative");
- }
- if (millis == 0) {
- while (isAlive()) {
- wait(0);
- }
- } else {
- while (isAlive()) {
- long delay = millis - now;
- if (delay <= 0) {
- break;
- }
- wait(delay);
- now = System.currentTimeMillis() - base;
- }
- }
- }
说明:
从代码中,我们可以发现。当 millis==0 时,会进入 while(isAlive()) 循环;即只要子线程是活的,主线程就不停的等待。
我们根据上面解释 join() 作用时的代码来理解 join() 的用法!
问题:
虽然 s.join() 被调用的地方是发生在"Father 主线程 "中,但是 s.join() 是通过 "子线程 s" 去调用的 join()。那么,join() 方法中的 isAlive() 应该是判断" 子线程 s"是不是 Alive 状态;对应的 wait(0) 也应该是 "让子线程 s" 等待才对。但如果是这样的话,s.join() 的作用怎么可能是" 让主线程等待,直到子线程 s 完成为止 "呢,应该是让" 子线程等待才对 (因为调用子线程对象 s 的 wait 方法嘛)"?
答案:wait() 的作用是让" 当前线程 "等待,而这里的" 当前线程 "是指当前在 CPU 上运行的线程。所以,虽然是调用子线程的 wait() 方法,但是它是通过 "主线程" 去调用的;所以,休眠的是主线程,而不是 "子线程"!
join() 示例在理解 join() 的作用之后,接下来通过示例查看 join() 的用法。
- // JoinTest.java的源码
- public class JoinTest {
- public static void main(String[] args) {
- try {
- ThreadA t1 = new ThreadA("t1"); // 新建"线程t1"
- t1.start(); // 启动"线程t1"
- t1.join(); // 将"线程t1"加入到"主线程main"中,并且"主线程main()会等待它的完成"
- System.out.printf("%s finish\n", Thread.currentThread().getName());
- } catch(InterruptedException e) {
- e.printStackTrace();
- }
- }
- static class ThreadA extends Thread {
- public ThreadA(String name) {
- super(name);
- }
- public void run() {
- System.out.printf("%s start\n", this.getName());
- // 延时操作
- for (int i = 0; i < 1000000; i++);
- System.out.printf("%s finish\n", this.getName());
- }
- }
- }
运行结果:
t1 start
t1 finish
main finish
结果说明:
运行流程如图
(01) 在 "主线程 main" 中通过 new ThreadA("t1") 新建 "线程 t1"。 接着,通过 t1.start() 启动" 线程 t1",并执行 t1.join()。
(02) 执行 t1.join() 之后," 主线程 main"会进入" 阻塞状态 "等待 t1 运行结束。" 子线程 t1"结束之后,会唤醒" 主线程 main"," 主线程 " 重新获取 cpu 执行权,继续运行。
以上所述是小编给大家介绍的 Java 线程之 join_动力节点 Java 学院整理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 PHPERZ 网站的支持!
来源: http://www.phperz.com/article/18/0105/356853.html