2012-01-23 50 views
1

我正在閱讀Java線程編程一本書由Paul Hyde。我進入了初級篇。我在Eclipse IDE中運行各種示例程序。Java線程編程示例 - 程序表現異常

public class TwoThreadAlive extends Thread { 
public void run() { 
    for (int i = 0; i < 10; i++) { 
     printMsg(); 
    } 
} 

public void printMsg() { 
    // get a reference to the thread running this 
    Thread t = Thread.currentThread(); 
    String name = t.getName(); 
    System.out.println("name=" + name); 
} 

public static void main(String[] args) { 
    TwoThreadAlive tt = new TwoThreadAlive(); 
    tt.setName("my worker thread"); 

    System.out.println("before start(), tt.isAlive()=" + tt.isAlive()); 
    tt.start(); 
    System.out.println("just after start(),tt.isAlive()=" + tt.isAlive()); 

    for (int i = 0; i < 10; i++) { 
     tt.printMsg(); 
    } 

    System.out 
      .println("at the end of main(), tt.isAlive()=" + tt.isAlive()); 
}} 

這個節目是給我每次運行它。但是它已經提到,輸出會有所不同的JVM會更加忙碌環境下,你switching.Can請告訴我,爲什麼它被賦予相同的輸出時間SAME輸出?

而且它給

at the end of main(), tt.isAlive()=true 

這本來

at the end of main(), tt.isAlive()=false 

請幫助我,這讓我瘋了。

+0

您可以打印您正在獲取的輸出... –

+0

嘗試增加for-loops中的迭代次數。也許工作量太少,沒有執行上下文切換。 – joergl

+1

將主方法內的循環增加到更高的值。你應該可以模擬它。當前程序輸出的方式在其他機器上不需要相同,調度線程留給操作系統和運行程序時的其他參數。 – panzerschreck

回答

4

不,輸出是正確的,因爲到main方法執行最後一次的時間println時,不能保證線程已經完成執行。最後打印之前添加tt.join();右:

tt.join(); 

System.out 
     .println("at the end of main(), tt.isAlive()=" + tt.isAlive()); 

現在主要的線程將被阻塞,直到tt完成,所以println僅執行後tt已經死了。

至於你的輸出總是相同的,10是一個太細的粒度值,很可能每個線程在完成上下文切換時完成打印所有內容。嘗試一個更大的價值。

+0

這意味着較小的值會傾向於每次運行時都會得到相同的輸出,那麼爲什麼作者在舉例時會提到小值。它令人困惑。 – C4CodeE4Exe

+0

@Suman_Sohal:你有多核心或單核心機器嗎?在多核上,它更可能發生,因爲這些線程真正並行執行,而在一個單核上它們不會。也有可能只是作者沒有真正測試他寫的內容,但根據我的經驗,只有10次迭代將(可能)永遠不會顯示交錯輸出。 – Tudor

+0

我有64位英特爾至強W3503.It有2個內核。 – C4CodeE4Exe

0

不是真的 乾淨 可讀代碼,我認爲printMsg()應該是靜態的,也許應放在主類。這樣你就可以注意到它的行爲不依賴於自定義線程類。由於它輸出當前線程名稱,因此您可以看到(爲了更高的迭代次數)您的TwoThreadAlive線程和主線程之間的JVM切換。
關於isAlive問題,TwoThreadAlive線程在主完成時可能尚未完成其執行。將主線程迭代更改爲100,將自定義線程更改爲10000以查看此效果。