本节摘要: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执行结束后继续执行
五、总结
- join()方法本质上是通过wait()方法实现阻塞的
- 如果子线程没有启动或者子线程执行结束,主线程不用等待可以继续执行
转载请注明作者及出处,并附上链接http://www.jianshu.com/u/ada8c4ee308b