zoukankan      html  css  js  c++  java
  • Java 多线程基础(九)join() 方法

    Java 多线程基础(九)join 方法

    一、join() 方法介绍

    join() 定义 Thread 类中的,作用是:把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。如:线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

    Thread 类中分别定义了: join() 、join(long millis) 和 join(long millis, int nanos) 三个方法。

    ①、join():等待线程t执行完毕。

    ②、join(long millis):等待 t 线程,等待时间是 millis 毫秒。

    ③、join(long millis, int nanos) :等待 t 线程,等待时间是 millis 毫秒 + nanos 纳秒。

    二、join() 示例

    public class JoinThread {
        
        public static void main(String[] args) {
            try {
                Thread t1 = new MyThread("t1");// 新建线程t1
                t1.start();// 启动线程
                t1.join(); // 将线程t1加入到主线程main中,并且主线程main()会等待它的完成
                System.out.println(Thread.currentThread().getName() + " main end.");
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
        static class MyThread extends Thread{
            public MyThread(String name) {
                super(name);
            }
            public void run() {
                System.out.println(Thread.currentThread().getName() + " run start.");
                for(int i = 0;i < 10000;i++)
                    ;
                System.out.println(Thread.currentThread().getName() + " run end.");
            }
        }
    }
    // 运行结果
    t1 run start.
    t1 run end.
    main main end.

    说明:

    ①、在“主线程main”中通过 new MyThread("t1") 新建“线程t1”。 接着,通过 t1.start() 启动“线程t1”,并执行t1.join()。
    ②、执行t1.join()之后,“主线程main”会进入“阻塞状态”等待t1运行结束。“子线程t1”结束之后,会唤醒“主线程main”,“主线程”重新获取cpu执行权,继续运行。

    具体过程图解:

    三、join() 解析(基于JDK 1.8)

    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;
        }
      }
    }
    public final synchronized void join(long millis, int nanos) throws InterruptedException {
      if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
      }
      if (nanos < 0 || nanos > 999999) { // 纳秒值范围在 (0 ~ 999999]
        throw new IllegalArgumentException("nanosecond timeout value out of range");
      }
      if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
        millis++;
      }
      join(millis);
    }

    上面源码是在Thread 类中定义的: join() 、join(long millis) 和 join(long millis, int nanos) 三个方法。

    从上面代码中可以看到,最主要的是 join(long millis) 方法,从该方法中可以发现:当传递的 millis  == 0 时,会进入while(isAlive())循环;即只要子线程是活的,主线程就不停的等待。

    问题
    虽然t1.join() 被调用的地方是发生在“main主线程”中,但是 t1.join() 是通过“子线程t1”去调用的 join()。那么,join() 方法中的 isAlive() 应该是判断“子线程t1”是不是 Alive 状态;对应的 wait(0) 也应该是“让子线程t1”等待才对。但如果是这样的话,t1.join() 的作用怎么可能是“让主线程等待,直到子线程s完成为止”呢,应该是让"子线程等待才对(因为调用子线程对象 t1 的 wait 方法嘛)"?
    答案

    wait() 的作用是让“当前线程”等待,而这里的“当前线程”是指当前在CPU上运行的线程。所以,虽然是调用子线程的 wait() 方法,但是它是通过“主线程”去调用的;所以,休眠的是主线程,而不是“子线程”!

  • 相关阅读:
    《构建之法(第三版)》第一章学习总结
    20189220余超 2019年密码与安全新技术讲座-课程总结报告
    学号20189220 2018-2019-2 《密码与安全新技术专题》第六周作业
    学号20189220余超 2018-2019-2 《密码与安全新技术专题》第七周作业
    20189200余超 2018-2019-2 移动平台应用开发实践作项目代码分析
    2018-2019-2学号20189220余超《移动平台应用程序开发实践》课程总结
    20189200余超 2018-2019-2 移动平台应用开发实践第十二周作业
    20189220余超 团队博客——阅读软件app
    20189200余超 2018-2019-2 移动平台应用开发实践第十一周作业
    20189200余超 2018-2019-2 移动平台应用开发实践第十周作业
  • 原文地址:https://www.cnblogs.com/lingq/p/13034593.html
Copyright © 2011-2022 走看看