目錄
1、join()簡介
join()方法的作用在一個線程內調用另一個線程實例的join()方法,表示線程在此阻塞,以等待相應的實例執行完成,join()內部是通過wait()方法實現的,因此調用join會自動釋放鎖
2、例子
public class ThreadDemo extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " begin run");
long startTime = System.currentTimeMillis();
try {
//模擬耗時處理
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName() + "執行時間爲:" + (endTime - startTime));
System.out.println(Thread.currentThread().getName() + "end run");
}
}
public class RunTest {
public static void main(String[] args) throws InterruptedException {
Thread.currentThread().setName("主線程");
System.out.println(Thread.currentThread().getName() + "begin run");
ThreadDemo threadDemo = new ThreadDemo();
threadDemo.setName("子線程");
threadDemo.start();
//阻塞等待
threadDemo.join();
System.out.println(Thread.currentThread().getName() + "end run");
}
}
運行結果:
從結果中我們可以看出,主線程調用子線程,當執行到join()方法時,子線程對象進入阻塞隊列,待子線程執行完畢後主線程繼續執行。
3、底層原理
join()方法源碼:
public final void join() throws InterruptedException {
join(0);
}
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {//若millis小於0則拋出異常
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {//若millis=0
while (isAlive()) {//判斷當前線程是否存活
wait(0);//永久等待,直到線程銷燬
}
} else {//millis大於0,阻塞指定時間,若時間過期,線程還未結束,就不等待了
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
從源碼可知,當參數millis爲0時,while循環使用isAlive()方法判斷當前線程是否存活(線程存活是指線程已經啓動並且還沒有死亡),wait(0)表示永遠等待。
注意,我們在源碼中看到只有wait()方法,卻沒看到notify()方法,那麼是由誰去喚醒在阻塞池中的線程呢?這個是在jvm中實現的, 一個線程執行結束後會執行該線程自身對象的notifyAll方法。
4、其他方法
- join(long 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()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
- join(long millis, int nanos):等待最多爲millis+nanos,最少爲1毫秒
public final synchronized void join(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
//當nanos大於500微妙時,或者毫秒值=0,則等待時間爲millis+1毫秒值,至少爲1毫秒
millis++;
}
join(millis);
}