join()
join()方法來自於Thread,join()方法的作用是 阻塞 調用該方法的線程,使其進入 TIMED_WAITING 狀態,直到被調用的線程執行完畢,原方法繼續執行。
如以下代碼,在主線程中調用join()方法,會首先執行run()方法中的代碼。
當我們把join()方法給註釋掉,會發現,首先執行了主線程的代碼。
即 調用join()方法阻塞了主線程,當run()方法執行完畢,主線程方法繼續執行
public static void main(String[] args) throws InterruptedException {
WaitJoinAndSleep w = new WaitJoinAndSleep();
Thread tOne = new Thread(w);
tOne.setName("1號選手");
tOne.start();
tOne.join();
System.out.println("main finished");
}
@Override
public void run() {
System.out.println("who first in:"+Thread.currentThread().getName());
System.out.println("Thread Name:+"+Thread.currentThread().getName());
}
//輸出
who first in:1號選手
Thread Name:+1號選手
main finished
//註釋掉tOne.join()後輸出
main finished
who first in:1號選手
Thread Name:+1號選手
join()方法源碼
通過join()方法源碼我們可以發現,join()方法最終是調用了wait()方法
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;
}
}
}
wait()
wait()方法來自於Object。
wait()方法的作用是讓當前線程等待,即執行wait方法的線程等待,釋放鎖。等待其它線程調用notify()方法時再繼續運行。
如下代碼,當主線程調用start()方法。此時並不會運行run()方法。因爲此時鎖被主線程佔有。當主線程中代碼調用wait()方法,主線程釋放鎖,線程one獲得鎖。在run()方法中執行notify()方法後,主線程被喚醒,繼續執行。
總結:wait()方法是讓運行它自身的線程等待。需要注意的是wait(),notify()和notifyAll()方法需要在synchronized中調用
public static void main(String[] args) throws InterruptedException {
WaitDemo w = new WaitDemo();
Thread one = new Thread(w);
synchronized (WaitDemo.class) {
// 開始啓動線程
System.out.println("thread started:"+Thread.currentThread().getName());
one.start();
// 調用wait()方法
System.out.println("begin start wait method");
WaitDemo.class.wait();
System.out.println("who started again");
}
}
@Override
public void run() {
synchronized (WaitDemo.class) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("who come first:"+Thread.currentThread().getName());
WaitDemo.class.notify();
}
}
// 輸出
thread started:main
begin start wait method
who come first:Thread-0
who started again
sleep()
sleep()方法屬於Thread
sleep()方法同樣可以造成線程阻塞,結合之前的代碼示例可以理解。調用sleep()方法並不會釋放鎖,而是讓當前線程“睡眠”,持有鎖的仍舊是當前線程,“睡眠時間”作爲參數,時間一到代碼繼續運行。
與wait()方法不同的是,sleep()方法可以在任意地方調用