Java线程之join_动力节点Java学院整理

 更新时间:2017年05月25日 10:09:15   投稿:mrr  
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学院整理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • 深入理解Java中的volatile关键字(总结篇)

    深入理解Java中的volatile关键字(总结篇)

    volatile这个关键字,不仅仅在Java语言中有,在很多语言中都有的,而且其用法和语义也都是不尽相同的。这篇文章主要介绍了Java中的volatile关键字,需要的朋友可以参考下
    2018-10-10
  • Mybatis-Plus更新时间字段不生效的解决

    Mybatis-Plus更新时间字段不生效的解决

    在使用Mybatis-Plus时,可能会遇到updateTime字段不自动更新的问题,通过分析,原因在于selectById获取旧数据后,如果字段已有值,更新操作不会自动填充更新时间,可以通过直接在实体中设置更新时间或在更新操作时指定时间来解决此问题
    2024-09-09
  • Java多线程之Interrupt中断线程详解

    Java多线程之Interrupt中断线程详解

    Interrupt 的其作用是"中断"线程, 但实际上线程仍会继续运行, 这是一个非常容易混淆的概念. Interrupt 的真正作用是给线程对象设置一个中断标记, 并不会影响线程的正常运行,需要的朋友可以参考下
    2021-05-05
  • Java字节码操纵框架ASM图文实例详解

    Java字节码操纵框架ASM图文实例详解

    这篇文章主要为大家介绍了Java字节码操纵框架ASM图文实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • 利用Jackson解决Json序列化和反序列化问题

    利用Jackson解决Json序列化和反序列化问题

    Jackson是一个用于处理Json数据的Java库,它提供了一系列功能,包括Json序列化和反序列化,所以本文就来讲讲如何利用利用Jackson解决Json序列化和反序列化的问题吧
    2023-05-05
  • Java调用ChatGPT的实现代码

    Java调用ChatGPT的实现代码

    这篇文章主要介绍了Java调用ChatGPT的实现代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • springboot获取properties属性值的多种方式总结

    springboot获取properties属性值的多种方式总结

    这篇文章主要介绍了springboot获取properties属性值的多种方式总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 关于SpringBoot的热部署方案

    关于SpringBoot的热部署方案

    这篇文章主要介绍了关于SpringBoot的热部署方案,每次修改代码就得将项目重启,重新部署,对于一些大型应用来说,重启时间需要花费大量的时间成本,本文就来详解热部署方案,需要的朋友可以参考下
    2023-05-05
  • Java实现商城订单超时取消功能

    Java实现商城订单超时取消功能

    大多数的B2C商城项目都会有限时活动,当用户下单后都会有支付超时时间,当订单超时后订单的状态就会自动变成已取消 ,这个功能的实现有很多种方法,本文的实现方法适合大多数比较小的商城使用。具体实现方式可以跟随小编一起看看吧
    2019-12-12
  • Java多线程中ThreadLocal解读

    Java多线程中ThreadLocal解读

    这篇文章主要介绍了Java多线程中ThreadLocal解读,  多线程访问同一个共享变量的时候容易出现并发问题,因此为了保证线程安全性,我们都会采用加锁的方式,而ThreadLocal是除加锁方式之外的另一种保证线程安全性的方法,需要的朋友可以参考下
    2023-09-09

最新评论