[英]What is the reason behind this behaviour(Thread)
我正在研究線程,並決定在我的重點代碼行運行之前和之后添加一些額外的文本,以供參考。 我希望在開頭和結尾處獲得一個“額外文本”。 然而......這並沒有發生,當我運行它時,第二個“額外文本”剛剛出現在第四個 position 中。 我是初學者,需要知道為什么會這樣……
- -代碼 - -
class Hi extends Thread{
public void run(){
for(int i=1; i<=5; i++){
System.out.println("HI!");
try{
Thread.sleep(500);
} catch(InterruptedException e){}
}
}
}
class Hey extends Thread{
public void run(){
for(int i=1; i<=5; i++){
System.out.println("HEY!");
try{
Thread.sleep(500);
} catch(InterruptedException e){}
}
}
}
public class MyClass {
public static void main(String[] args){
Hi hiObj = new Hi();
Hey heyObj = new Hey();
System.out.println("extra-text");
hiObj.start();
heyObj.start();
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("extra-text");
}
}
- -輸出 - -
extra-text
HI!
HEY!
extra-text
HEY!
HI!
HEY!
HI!
HEY!
HI!
HEY!
HI!
這是一個常見的並發錯誤。
程序的 main 方法在主線程上運行。 因此,在您啟動hiObj
和heyObj
線程之前,您已經有了一個線程。 啟動兩個新線程后,您將擁有三個。 每個都同時執行。 這意味着每個線程都可以執行代碼而無需等待其他線程。 線程之間不保證順序。
這會導致您觀察到的行為。 在hiObj
或heyObj
啟動之前,在主線程上運行的 main 方法會打印"extra-text"
。 接下來,啟動 hiObj 和 heyObj。 主線程到達Thread.currentThead().sleep(10)
行,這導致它暫停執行 10 毫秒。 在大多數機器(包括您的機器)上,這足以讓其他兩個線程開始執行。 每個線程在其run
方法中開始for
循環並打印"HI"
或"HEY"
。 因此,output 的前三行是(不保證"HI"
和"HEY"
的順序):
"extra-text"
"HI"
"HEY"
接下來, hiObj
和heyObj
線程到達Thread.sleep(500)
行,這導致它們暫停執行 500 毫秒。 10 毫秒過去后,主線程將完成睡眠並恢復。 請注意, hiObj
或heyObj
線程現在都不能恢復。 因此,打印的下一行將是main
中執行的下一行。 這是"extra-text"
。 因此,預期的 output 是:
"extra-text"
"HI"
"HEY"
"extra-text"
在接下來的幾秒鍾內,來自hiObj
和heyObj
線程的剩余打印將發生。 在 Java 中,只有在所有其他線程都退出后,主線程才會退出(除非調用System.exit
或存在未捕獲的異常)。 在這種情況下,這意味着程序只有在main
執行結束並且hiObj
和heyObj
的 run 方法都返回時才會退出。
要更改程序以使最后一個"extra-text"
始終打印在最后,您必須使主線程等待hiObj
和heyObj
線程完成。 在 Java 中, Thead
上有一個名為join
的方法,它會導致調用線程等待直到加入的線程死亡。 在您的程序中,您可以將MyClass
修改為如下所示:
public class MyClass {
public static void main(String[] args){
Hi hiObj = new Hi();
Hey heyObj = new Hey();
System.out.println("extra-text");
hiObj.start();
heyObj.start();
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
hiObj.join();
heyObj.join();
System.out.println("extra-text");
}
}
通過此更改, main
將首先等待hiObj
完成,然后等待heyObj
完成,然后再打印"extra-text"
。
如果你擺脫
Thread.currentThread().sleep(10);
在主方法中,您將看到您的兩個額外文本在執行后立即打印到控制台。 通過使用 sleep(10),您只需延遲第二個額外文本,同時您的 2 個線程打印它們的第一個 output。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.