2011-04-12 51 views
0

考慮此程序:Java線程疑問

public class test { 
    public static void main(String [] args){ 
     Runnable r = new Runnable() { 
      public void run() { 
       System.out.print("foo"); 
      } 
     }; 
     Thread t = new Thread(r) { 
      public void run() { 
       System.out.print("bar"); 
      } 
     }; 
     t.start(); 
    } 
} 

在運行輸出

bar 

我想知道爲什麼會這樣。

我的理解:

我們實例實現通過重寫run方法的Runnable的匿名內部類。並將其分配給r。

接下來我們將這個runnable傳遞給Thread類的構造函數。但是我們也創建了一個新的匿名內部類,通過覆蓋運行來擴展Thread。

所以我們現在有兩種運行方法,第二種將優先於第一種。

我很困惑,請糾正我,如果我錯了。

也是在現實世界的Java編程中使用這種瘋狂的東西? (我的教授說是,那是什麼讓我們繼續前進:D)。

回答

3

雖然您將Runnable實例傳遞給構造函數,但您會以這種方式重寫run方法,以致它不使用r

2

會發生什麼是標準Thread.run方法調用run在您傳入的Runnable。在你的情況,你要重寫線程的行爲,並與一個run方法忽略了給定Runnable替換它。

這樣的瘋狂事不幸發生在現實世界中。這就是爲什麼使用靜態分析工具和單元測試確保獲得您期望的行爲是個好主意:)

0

方法Thread.run()通常會查看線程是否構建了可運行的。在這種情況下,它調用Runnable.run(),否則什麼也不做。您通過覆蓋Thread.run()來更改此行爲,因此您的runnable永遠不會被調用。

1

當您覆蓋其run()方法時,您正在覆蓋線程的默認行爲。通過這種方式,您可以控制訂單以及是否運行r

public void run() { // ignores "r" 
    System.out.print("bar"); 
} 

public void run() { 
    super.run(); // runs "r" first. 
    System.out.print("bar"); 
} 

public void run() { 
    System.out.print("bar"); 
    super.run(); // runs "r" second. 
} 

public void run() { 
    super.run(); // runs "r" first. 
    System.out.print("bar"); 
    super.run(); // and runs "r" second. 
} 

public void run() { 
    r.run(); // runs "r" first. 
    System.out.print("bar"); 
    r.run(); // and runs "r" second. 
}