多執行緒——join()、sleep()
阿新 • • 發佈:2019-01-26
Thread類的方法中有一個join()方法,它是普通的例項方法,根據Java api,該方法有如下三種形式:
void join(): Waits for this thread to die.
void join(long millis): Waits at most millis milliseconds for this thread to die.
void join(long millis, int nanos): Waits at most millis milliseconds plus nanos nanoseconds for this thread to die.
該方法的作用是“等待該執行緒終止”,一直等待,直到程終止,而帶引數的方法的作用是“ 等待該執行緒終止,至多等待多少毫秒數 (或毫秒數+納秒數)”。
在此之前,我對這個方法一直有兩個疑問,困惑不解:
- 為什麼這個方法的作用是等待該執行緒終止,為什麼它的名字是“加入”的意思?
- 在這個等待的關係中,到底是誰等待誰?
在看了很多人的部落格、看了這個方法的原始碼、看了《Java多執行緒程式設計核心技術》這本書和實踐之後,我的理解如下,作為自我學習總結。
1. join()的原始碼分析
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)
方法的原始碼如上所示,首先該方式是synchronized,其次它的實現原理是呼叫了wait()方法。
2. join()/wait()與sleep()的區別
由上,所以join()和sleep()
這兩個方法的區別,本質上是wait()和sleep()
這兩個方法的區別。
wait()和sleep()的區別:
- 這兩個方法來自不同的類,wait()方法來自Object類,sleep()方法來自Thread類;
- wait()方法有三種形式:
wait()、wait(long timeout)、wait(long timeout, int nanos)
,而sleep()方法兩種形式:sleep(long millis)、sleep(long millis, int nanos)
,即sleep()方法沒有無參形式。其次,sleep()方法是靜態方法。 - 其實區別主要還是來自於這兩個方法對同步的處理上:wait()方法會釋放鎖,sleep()方法不釋放鎖。在sleep()方法的原始碼中有這樣一句話:
The thread does not lose ownership of any monitors.
所以join()和sleep()
這兩個方法的區別,來自於它們對同步的處理上,如上第三條。
3. join()的作用分析
join()方法具有使執行緒依次序列執行的作用,也就是使執行緒排隊執行。對於t.join()語句,其中的等待關係如下:
join()方法的作用是使執行緒t正常執行run()
方法中的任務,而使當前執行緒s一直等待執行緒t終止,
在很多情況下,主執行緒生成並起動了子執行緒,所以執行緒s有可能是主執行緒,也有可能是其它子執行緒。
也就是t.join()方法後面的程式碼,只有等到t執行緒結束了才能執行。join()方法的使用方式是線上程t啟動後直接呼叫。
程式碼例項:
功能:三個執行緒,一個列印A,一個列印B,一個列印C,打印出6個連續的ABC。
/*
* 三個執行緒, 一個列印A, 一個列印B, 一個列印C, 打印出6個連續的ABC.
*/
public class PrintABC implements Runnable {
@Override
public void run() {
if(Thread.currentThread().getName().equals("A")){
System.out.print("A");
}
if(Thread.currentThread().getName().equals("B")){
System.out.print("B");
}
if(Thread.currentThread().getName().equals("C")){
System.out.print("C");
}
}
public static void main(String[] args) throws InterruptedException {
for(int i=0; i<6; i++){
PrintABC r = new PrintABC();
Thread A = new Thread(r, "A");
A.start();
A.join();
Thread B = new Thread(r, "B");
B.start();
B.join();
Thread C = new Thread(r, "C");
C.start();
C.join();
}
}
}
執行結果:
嘻嘻~