java 线程方法join简单用法实例总结

 更新时间:2019年11月05日 11:28:35   作者:苍青浪  
这篇文章主要介绍了java 线程方法join简单用法,结合实例形式总结分析了Java线程join方法的功能、原理及使用技巧,需要的朋友可以参考下

本文实例讲述了java 线程方法join简单用法。分享给大家供大家参考,具体如下:

虽然关于讨论线程join方法的博客已经很多了,不过个人感觉挺多都讨论得不够全面,所以我觉得有必要对其进行一个全面的总结。

一、作用

Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。具体看代码:

public class JoinTest {
  public static void main(String [] args) throws InterruptedException {
    ThreadJoinTest t1 = new ThreadJoinTest("小明");
    ThreadJoinTest t2 = new ThreadJoinTest("小东");
    t1.start();
    /**join的意思是使得放弃当前线程的执行,并返回对应的线程,例如下面代码的意思就是:
     程序在main线程中调用t1线程的join方法,则main线程放弃cpu控制权,并返回t1线程继续执行直到线程t1执行完毕
     所以结果是t1线程执行完后,才到主线程执行,相当于在main线程中同步t1线程,t1执行完了,main线程才有执行的机会
     */
    t1.join();
    t2.start();
  }
}
class ThreadJoinTest extends Thread{
  public ThreadJoinTest(String name){
    super(name);
  }
  @Override
  public void run(){
    for(int i=0;i<1000;i++){
      System.out.println(this.getName() + ":" + i);
    }
  }
}

上面程序结果是先打印完小明线程,在打印小东线程;

上面注释也大概说明了join方法的作用:在A线程中调用了B线程的join()方法时,表示只有当B线程执行完毕时,A线程才能继续执行。注意,这里调用的join方法是没有传参的,join方法其实也可以传递一个参数给它的,具体看下面的简单例子:

public class JoinTest {
  public static void main(String [] args) throws InterruptedException {
    ThreadJoinTest t1 = new ThreadJoinTest("小明");
    ThreadJoinTest t2 = new ThreadJoinTest("小东");
    t1.start();
    /**join方法可以传递参数,join(10)表示main线程会等待t1线程10毫秒,10毫秒过去后,
     * main线程和t1线程之间执行顺序由串行执行变为普通的并行执行
     */
    t1.join(10);
    t2.start();
  }
}
class ThreadJoinTest extends Thread{
  public ThreadJoinTest(String name){
    super(name);
  }
  @Override
  public void run(){
    for(int i=0;i<1000;i++){
      System.out.println(this.getName() + ":" + i);
    }
  }
}

上面代码结果是:程序执行前面10毫秒内打印的都是小明线程,10毫秒后,小明和小东程序交替打印。

所以,join方法中如果传入参数,则表示这样的意思:如果A线程中掉用B线程的join(10),则表示A线程会等待B线程执行10毫秒,10毫秒过后,A、B线程并行执行。需要注意的是,jdk规定,join(0)的意思不是A线程等待B线程0秒,而是A线程等待B线程无限时间,直到B线程执行完毕,即join(0)等价于join()。

二、join与start调用顺序问题

上面的讨论大概知道了join的作用了,那么,入股 join在start前调用,会出现什么后果呢?先看下面的测试结果

public class JoinTest {
  public static void main(String [] args) throws InterruptedException {
    ThreadJoinTest t1 = new ThreadJoinTest("小明");
    ThreadJoinTest t2 = new ThreadJoinTest("小东");
    /**join方法可以在start方法前调用时,并不能起到同步的作用
     */
    t1.join();
    t1.start();
    //Thread.yield();
    t2.start();
  }
}
class ThreadJoinTest extends Thread{
  public ThreadJoinTest(String name){
    super(name);
  }
  @Override
  public void run(){
    for(int i=0;i<1000;i++){
      System.out.println(this.getName() + ":" + i);
    }
  }
}

上面代码执行结果是:小明和小东线程交替打印。

所以得到以下结论:join方法必须在线程start方法调用之后调用才有意义。这个也很容易理解:如果一个线程都没有start,那它也就无法同步了。

三、join方法实现原理

有了上面的例子,我们大概知道join方法的作用了,那么,join方法实现的原理是什么呢?

其实,join方法是通过调用线程的wait方法来达到同步的目的的。例如,A线程中调用了B线程的join方法,则相当于A线程调用了B线程的wait方法,在调用了B线程的wait方法后,A线程就会进入阻塞状态,具体看下面的源码:

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;
      }
    }
  }

从源码中可以看到:join方法的原理就是调用相应线程的wait方法进行等待操作的,例如A线程中调用了B线程的join方法,则相当于在A线程中调用了B线程的wait方法,当B线程执行完(或者到达等待时间),B线程会自动调用自身的notifyAll方法唤醒A线程,从而达到同步的目的。

更多java相关内容感兴趣的读者可查看本站专题:《Java进程与线程操作技巧总结》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总

希望本文所述对大家java程序设计有所帮助。

相关文章

  • 详解Java中int和Integer的区别

    详解Java中int和Integer的区别

    这篇文章主要介绍了Java中int和Integer的区别文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • 基于java 线程的几种状态(详解)

    基于java 线程的几种状态(详解)

    下面小编就为大家带来一篇基于java 线程的几种状态(详解)。小编觉得挺不错的,现在就想给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • Mybatis Plus 代码生成器的实现

    Mybatis Plus 代码生成器的实现

    这篇文章主要介绍了Mybatis Plus 代码生成器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • MyBatis查询数据返回null的解决

    MyBatis查询数据返回null的解决

    本文主要介绍了MyBatis查询数据返回null的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Java程序图形用户界面设计之按钮与布局

    Java程序图形用户界面设计之按钮与布局

    图形界面(简称GUI)是指采用图形方式显示的计算机操作用户界面。与早期计算机使用的命令行界面相比,图形界面对于用户来说在视觉上更易于接受,本篇精讲Java语言中关于图形用户界面的按钮和布局部分
    2022-02-02
  • 基于JWT的spring boot权限验证技术实现教程

    基于JWT的spring boot权限验证技术实现教程

    这篇文章主要给大家介绍了关于基于JWT的spring boot权限验证技术实现的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Spring中的SpringData详细说明

    Spring中的SpringData详细说明

    这篇文章主要介绍了Spring中的SpringData详细说明,Spring Data 是Spring 的一个子项目, 旨在统一和简化对各类型持久化存储, 而不拘泥于是关系型数据库还是NoSQL 数据存储,需要的朋友可以参考下
    2023-11-11
  • java学习之一维数组中重复元素的去除

    java学习之一维数组中重复元素的去除

    关于一维数组中有重复的元素该怎么剔除,作为java初学者的我整理出不调用任何特殊库的基础方法,这种思想在其他语言也适用,有需要的朋友可以借鉴参考下
    2021-09-09
  • Mybatis开发要点-resultType和resultMap有什么区别详解

    Mybatis开发要点-resultType和resultMap有什么区别详解

    本文主要介绍了Mybatis开发要点-resultType和resultMap有什么区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Java枚举详解及使用实例(涵盖了所有典型用法)

    Java枚举详解及使用实例(涵盖了所有典型用法)

    这篇文章主要介绍了Java枚举详解及使用实例(涵盖了所有典型用法),本文直接给出实例代码,代码中包含详细注释,需要的朋友可以参考下
    2015-05-05

最新评论