技术干货程序员

JAVA多线程09-基础篇-线程等待join

2017-10-27  本文已影响0人  x_coder

本节摘要:join()的功能介绍,基本用法,源码分析,代码示例

一、功能介绍

join()使当前线程等待子线程执行完毕后,才能继续执行

二、基本用法

    public static void main(String[] args) {
        //1.new 一个线程 t1
        MyThread t1= new MyThread("t1");
        //2. 启动 t1
        t1.start();
        try {
            //3. t1线程开始执行,当前线程等待t1执行后才能继续执行
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

三、源码分析

join()方法在Thread类中,有三个重载的join方法,如果被中断会抛出InterruptedException异常

注:以下代码解析以第二部分的样例代码举例(下同)

3.1 join()方法解析

 // Waits for this thread to die.
public final void join() throws InterruptedException {
        join(0);
    }

注释的含义是等待这个线程死亡,也就是说:当前线程(main)会等待调用join()方法的线程(t1)死亡,才能继续执行,否则一直等待。

3.2 join(millis)方法解析

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()) {//如果子线程一直存活,当前线程会一直等待,这里就是join核心作用体现
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

这是一个synchronized方法,核心是isAlive()和wait()方法,我们先看一下isAlive()方法

    /**
     * Tests if this thread is alive. A thread is alive if it has
     * been started and has not yet died.
     */
    public final native boolean isAlive();

这是一个本地方法,大概意思是测试这个线程(this thread)是否存活,如果线程可运行且没有死亡就是存活的。

那么问题来了:这个线程是哪个线程呢?
回答:我们发现 isAlive()方法和join()方法都描述为this thread,所以this thread 就是调用join()方法的线程,即t1线程。

接下来看一下wait()方法
我们知道,wait()方法属于java.lang.Object 类,调用线程必须获得对象锁才能调用wait()方法,而join方法又是synchronized方法,也就是说当前线程(main)在调用t1.join()方法时,获得到了t1的对象锁,这段逻辑类似如下代码

synchronized(t1){
    while(t1.isAlive())
          t1.wait(0);
}

当调用线程(main)执行t1.wait(0)时,调用线程(main)会释放t1的锁,一直等待t1线程执行结束(死亡),调用线程(main)才会继续执行

三、代码示例

public class JoinDemo {

    public static void main(String[] args) {
        MyThread threadA = new MyThread("t1");
        System.out.println(Thread.currentThread().getName() + " start t1");
        threadA.start();
        try {
            System.out.println(Thread.currentThread().getName() + " call thread.join()");
            threadA.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " continue");
    }

    static class MyThread extends Thread {
        public MyThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + "---" + i);
            }
        }

    }
}

输出结果:
main start t1
main call thread.join()
t1---0
t1---1
t1---2
t1---3
t1---4
main continue

四、结果分析

主线程main会等待线程t1执行结束后继续执行

五、总结

转载请注明作者及出处,并附上链接http://www.jianshu.com/u/ada8c4ee308b

上一篇 下一篇

猜你喜欢

热点阅读