join()方法的作用,是等待这个线程结束;
也就是说,t.join()方法阻塞调用此方法的线程(calling thread)进入 TIMED_WAITING 状态,直到线程t完成,此线程再继续;
通常用于在main()主线程内,等待其它线程完成再结束main()主线程。
举个例子:
public class JoinTester01 implements Runnable {
private String name;
public JoinTester01(String name) {
this.name = name;
}
public void run() {
System.out.printf("%s begins: %s\n", name, new Date());
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s has finished: %s\n", name, new Date());
}
public static void main(String[] args) {
Thread thread1 = new Thread(new JoinTester01("One"));
Thread thread2 = new Thread(new JoinTester01("Two"));
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Main thread is finished");
}
}
若没有join()语句就变成了如下结果:
join()源码:
/**
* Waits at most <code>millis</code> milliseconds for this thread to
* die. A timeout of <code>0</code> means to wait forever.
*/
//此处A timeout of 0 means to wait forever 字面意思是永远等待,其实是等到t结束后。
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()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
说明:
从代码中,我们可以发现。当millis==0时,会进入while( isAlive() )循环;即只要子线程是活的,主线程就不停的等待。
我们根据上面解释join()作用时的代码来理解join()的用法!
wait()的作用是让“当前线程”等待,而这里的“当前线程”是指当前运行的线程。虽然是调用子线程的wait()方法,但是它是通过“主线程”去调用的;所以,休眠的是主线程,而不是“子线程”!
这样理解: 例子中的Thread t只是一个对象 , isAlive()判断当前对象(例子中的t对象)是否存活, wait()阻塞的是当前执行的线程(例子中的main方法)
可以看出,Join方法实现是通过wait()。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(),直到该对象唤醒main线程 ,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁。
例子来源为以下博主: