2011-12-10 78 views
0

我想了解一個Thread對象狀態的線程完成後後。我讀過一本書,一旦線程完成其run()方法,線程對象仍然是頭上的有效對象,仍然可以用作實例對象,您仍然可以調用它的方法。我決定嘗試以下示例:運行線程的run()方法的線程已經完成

class DieThread implements Runnable{ 

    int y = 0; 

    public void run(){ 
     for(int x=0; x<100; x++){ 
      System.out.println("    " + Thread.currentThread().getName()); 
      System.out.println("y is " + y); 
      y++; 
      System.out.println("y is " + y); 
     } 
    } 
} 

class ZiggyTest2{ 
    public static void main(String[] args){  

     DieThread d = new DieThread(); 

     Thread a = new Thread(d); 
     Thread b = new Thread(d); 
     Thread c = new Thread(d); 

     a.start(); 
     b.start(); 
     c.start(); 

     try{ 
      a.join(); 
      b.join(); 
      c.join(); 
     }catch(Exception e){ 
      System.out.println(e); 
     } 

     System.out.println("Running C's Run"); 
     c.run();   
    } 
} 

main()通過使用join()等待其他3個線程完成。然後調用c的run()方法,但由於某種原因,它不會從run()方法中打印任何內容。這是我運行上述程序後輸出的最後幾行。

y is 287 
y is 287 
y is 288 
y is 289 
      Thread-1 
      Thread-0 
y is 289 
y is 289 
y is 290 
y is 291 
      Thread-1 
      Thread-0 
y is 291 
y is 291 
y is 292 
y is 293 
      Thread-1 
      Thread-0 
y is 293 
y is 293 
y is 294 
y is 295 
      Thread-0 
y is 295 
y is 296 
      Thread-0 
y is 296 
y is 297 
      Thread-0 
y is 297 
y is 298 
      Thread-0 
y is 298 
y is 299 
      Thread-0 
y is 299 
y is 300 
Running C's Run 

即使線程已經完成,我期待y因爲c.run()調用的值爲400。

任何想法?

謝謝

+1

你確定你不想叫d.run()?此外,我很驚訝沒有破壞,因爲你有3個線程遞增相同的變量,沒有鎖定。 – Thomas

+0

是的,我想在完成後運行線程對象。 – ziggy

回答

1

的理由讓你在觀察什麼是埋在Thread的實施狀況後null類。

當您致電c.run()時,您正在調用線程對象的run方法。這被指定爲調用target對象的run方法(即,在Thread構造提供的可運行的),如果它不是null。如果targetnull那麼Thread.run()方法不起作用。

OK,所以你提供一個非空target

事實上,當一個Thread完成時,Thread.exit()方法被調用來清理。而清理所做的其中一件事是將null分配到target。 (該代碼有一條關於需要積極清除引用的註釋以及一個缺陷ID,但遺憾的是缺少相應的缺陷報告,因此無法知道它們的真實原因。)

無論如何,底線是你不能通過調用Thread.run()重新運行目標對象的run()方法。但是你可以直接調用目標對象的run()方法...如果你有目標引用。

+0

如果Thread.exit將爲目標賦予null,那麼不會調用目標的run方法會導致NullPointerException?我只是在線程完成後嘗試調用d.run(),但沒有得到NullPointerException,即使此時該對象應該爲空。 – ziggy

+0

你不會得到一個NPE。再次閱讀我的第二段...特別是關於'target'爲'null'的情況。更好的是,你自己來看看Thread類的源代碼。 –

+0

*所以不可能知道他們這樣做的真正原因* >> Stephen,自從Oracle接管後,它的bug從1.0.2開始,他們刪除了很多bug引用。我清楚地記得在1999年的代碼,仍然是一樣的。無論哪種方式,由於線程泄漏和其他原因,積極的刪除幫助gc。現在它仍然很酷,因爲有時線程仍然泄漏。 – bestsss

3

如果擴展Thread類,它會工作。現在,檢查Runnable目標這Thread.exit()

1

同步訪問對象DieThread

synchronized(this) { 
    System.out.println("    " + Thread.currentThread().getName()); 
    System.out.println("y is " + y); 
    y++; 
    System.out.println("y is " + y); 
} 
+0

謝謝。我並不是很擔心對象的狀態。我對線程完成線程後發生的事情更感興趣。 – ziggy

相關問題