Java Thread.join()详解

1.用法

join是Thread类的一个方法,启动线程后直接调用,例如:

Thread t = new AThread(); 
t.start(); 
t.join();

2.join方法的作用

       在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。

       即join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。

3.示例

package com.roocom.test2;

/**
 * 
 * @author yanling
 * @time 2019-2-21 00:41:08
 */
public class TestDemo {
	public static void main(String[] args) {
		String threadName = Thread.currentThread().getName();
		System.out.println(threadName + " 开始执行...");
		BThread bt = new BThread();
		bt.setName("线程bt");
		AThread at = new AThread(bt);
		at.setName("线程at");
		try {
			bt.start();
			Thread.sleep(2000);
			System.out.println("暂停2秒");
			at.start();
			at.join();
		} catch (Exception e) {
			System.out.println("Exception from main");
		}
		System.out.println(threadName + " 执行结束...");
	}
}

class BThread extends Thread {
	public BThread() {
		super("[BThread] Thread");
	};

	public void run() {
		String threadName = Thread.currentThread().getName();
		System.out.println(threadName + " 开始执行...");
		try {
			for (int i = 0; i < 5; i++) {
				System.out.println(threadName + " loop at " + i);
				Thread.sleep(1000);
			}
			System.out.println(threadName + " 运行结束...");
		} catch (Exception e) {
			System.out.println("Exception from " + threadName + ".run");
		}
	}
}

class AThread extends Thread {
	BThread bt;

	public AThread(BThread bt) {
		super("[AThread] Thread");
		this.bt = bt;
	}

	public void run() {
		String threadName = Thread.currentThread().getName();
		System.out.println(threadName + " 开始执行...");
		try {
			bt.join();
			System.out.println(threadName + " 执行结束...");
		} catch (Exception e) {
			System.out.println("Exception from " + threadName + ".run");
		}
	}
}

执行结果

main 开始执行...
线程bt 开始执行...
线程bt loop at 0
线程bt loop at 1
暂停2秒
线程at 开始执行...
线程bt loop at 2
线程bt loop at 3
线程bt loop at 4
线程bt 运行结束...
线程at 执行结束...
main 执行结束...

修改下mian方法,使得mian线程不需要等待线程at。

public class TestDemo {
	public static void main(String[] args) {
		String threadName = Thread.currentThread().getName();
		System.out.println(threadName + " 开始执行...");
		BThread bt = new BThread();
		bt.setName("线程bt");
		AThread at = new AThread(bt);
		at.setName("线程at");
		try {
			bt.start();
			Thread.sleep(2000);
			System.out.println("暂停2秒");
			at.start();
//			at.join();  注释掉这行,使mian线程不需要等待线程at执行结束
		} catch (Exception e) {
			System.out.println("Exception from main");
		}
		System.out.println(threadName + " 执行结束...");
	}
}

运行结果

线程bt loop at 0
线程bt loop at 1
暂停2秒
线程bt loop at 2
main 执行结束...
线程at 开始执行...
线程bt loop at 3
线程bt loop at 4
线程bt 运行结束...
线程at 执行结束...

4.源码解读

进入bt.join方法看一下它的JDK源码:

    /**
     * Waits for this thread to die.
     * 等待线程执行完成
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final void join() throws InterruptedException {
        join(0);
    }

我们再进入到join方法里面去

 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) {             //如果时执行的join(0)
            while (isAlive()) {        //如果线程是运行状态,就会执行下面的等待
                wait(0);               
            }
        } else {                       //如果是执行的join(time)
            while (isAlive()) {               //如果线程时运行状态
                long delay = millis - now;    
                if (delay <= 0) {
                    break;
                }
                wait(delay);                 //等待delay时间后自动返回继续执行
                now = System.currentTimeMillis() - base;
            }
        }
 }

通过源码我们可以看到,其核心代码就是下面这段 

while (isAlive()) {        //调用join方法线程是运行时状态
      wait(0);             //进入等待
 }

源码中while(isAlive()),其实相当于while(this.isAlive())校验线程是不是运行状态,如果是就执行wait(0),wait(0)是什么意思呢,查看下面wait()方法源码,其实wait()方法就是调用了wait(0)方法实现的,wait(0)就是让其一直等待。到这里会发现,其实join方法本质就是利用上面的线程实例作为对象锁的原理,当线程终止时,会调用线程自身的notifyAll()方法,通知所有等待在该线程对象上的线程的特征。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值