join的作用
join的作用是将另一线程加入到当前线程中,并串行执行。
public class JoinTest {
public static void main(String[] args) throws Exception{
Thread thread = new Thread(new JoinTask());
thread.start();
thread.join();
System.out.println("Main end.");
}
}
class JoinTask implements Runnable {
@Override
public void run() {
try{
System.out.println("Join Task Running...");
TimeUnit.SECONDS.sleep(3);
System.out.println("Join Task End.");
}catch (Exception ex) {
ex.printStackTrace();
}
}
}
执行结果为:
Join Task Running...
Join Task End.
Main end.
JoinTask线程被加入到Main线程中,Main线程等待JoinTask完成后再继续执行。
join()
还有一个重载方法join(long milins)
,该方法的作用是让main线程等待指定时间,待时间到后,被join的线程与主线程开始并行执行。
将上述代码中的thread.join
修改为thread.join(100)
,执行结果为:
Join Task Running...
Main end.
Join Task End.
main函数比JoinTask先执行完成。
join与start的关系
若向上述代码中start()
和join()
的调用顺序修改为
thread.join();
thread.start();
那么,执行结果为
Main end.
Join Task Running...
Join Task End.
也就是说,join方法并没有起作用。这也不难理解,因为join是真的线程而言的,如果在调用join的时候,在系统中还没初始化一个就绪状态的线程,那对join对调用是完全没有意义的。
综上所属,在调用start()
的调用必须在join()
之前。
join的原理
join底层基wait/notify
实现,下面看一下join方法的源码:
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;
}
}
当在线程thread上调用join方法时,就相当于在main线程上调用了thread.wait()方法,当被join的线程执行完成时,会自动在thread对象上调用notify方法,也就是唤醒main线程。