说明
Thread的join方法的作用是等待该线程执行完。例如,假设线程对象是ta,在ta上调用join方法,意思是等待线程ta执行完。
利用这个方法,可以人为控制线程执行的顺序。
join方法有几个形式:
void join() 相当于调用join(0)
join(long millis)
join(long millis, int nanos)
join(Duration duration)
如果join方法的时间参数值是0,表示一直等待。
一个示例
在下面的代码中,在主线程中创建了threadA和threadB两个线程。
先启动threadA,然后调用threadA.join();
再启动threadB,然后调用threadB.join();
package com.thb;
import java.util.concurrent.TimeUnit;
public class Test6 {
public static void main(String[] args) throws InterruptedException {
// 创建一个线程
Thread threadA = new Thread(() -> {
System.out.println("进入线程: " + Thread.currentThread().getName());
try {
System.out.println(Thread.currentThread().getName() + " 睡眠");
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 被唤醒");
System.out.println("离开线程: " + Thread.currentThread().getName());
}, "threadA");
// 创建一个线程
Thread threadB = new Thread(() -> {
System.out.println("进入线程: " + Thread.currentThread().getName());
try {
System.out.println(Thread.currentThread().getName() + " 睡眠");
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 被唤醒");
System.out.println("离开线程: " + Thread.currentThread().getName());
}, "threadB");
// 启动threadA
threadA.start();
// 等待threadA执行完
threadA.join();
System.out.println("*".repeat(60));
// 启动threadB
threadB.start();
// 等待threadB执行完
threadB.join();
System.out.println("*".repeat(60));
System.out.println("当前线程: " + Thread.currentThread().getName());
}
}
执行输出:
进入线程: threadA
threadA 睡眠
threadA 被唤醒
离开线程: threadA
************************************************************
进入线程: threadB
threadB 睡眠
threadB 被唤醒
离开线程: threadB
************************************************************
当前线程: main
无论执行多少次,上面的输出是一样的。从上面的输出可以看出,先执行完了threadA,然后再执行threadB。
join方法源码分析
看Thread.java的源码,在join方法中,关键的是下面的判断isAlive()
和等待wait(0)
:
我们以上面的threadA
为例:
isAlive()
方法是在threadA
这个对象上调用的,即threadA.isAlive()
,它就是判断threadA有没有结束。这个理解起来没有困难。- 如果
threadA
没有结束,就调用wait(0)
方法,其实也是threadA.wait(0)
。这个我开始理解不了。我开始认为是让threadA
等待,这跟让threadA
执行完的目标看似矛盾。但其实,这个代码语句是在主线程中执行threadA.join()
调用走进来的,当前正在运行的线程是主线程,而Java对象的wait
方法是让当前线程等待,直到被唤醒,也就是让主线程等待。