2012-06-26 114 views
2

我只是想知道結果會是什麼,如果我子類延伸Thread一類,我寫了下面的代碼和測試:重寫run()方法

class A extends Thread { 
    public A() { 
     this.start(); 
    } 
    public void run() { 
     System.out.println(" in A " + Thread.currentThread().getName()); 
    } 
} 

class B extends A { 
    public void run() { 
     System.out.println(" in B " + Thread.currentThread().getName()); 
    } 
} 

public class OverrideRun { 
    public static void main(String[] args) { 
     A a = new A(); 
     B b = new B(); 
    }  
} 

,其結果是:

線程0 B中
線程1

但我不明白爲什麼是兩個線程s是否被創建?

回答

3

這是因爲B b = new B();語句不會調用B類的參數參數,並且不會調用類A的參數參數構造函數(Default)。

這是由於構造函數鏈。

2

那是因爲你創建兩個線程(兩個對象從Thread繼承),在這裏:

public static void main(String[] args) { 
    A a = new A(); // #1 
    B b = new B(); // #2 
} 
2

,但我不明白爲什麼會創建兩個線程?

,因爲你是在A()構造開始他們兩個線程開始:

public A() { 
    this.start(); 
} 

,你是構建兩個對象 - 一個A和延伸A一個B

A a = new A(); 
    B b = new B(); 

默認情況下,當你說new B(),因爲它沒有一個無參數的構造函數,它會調用蘇佩的無參數的構造函數rclass。所以它會調用啓動線程的A構造函數。見Java documentation here。引用:

您不必爲您的課程提供任何構造函數,但是在做這些時必須小心。編譯器自動爲任何沒有構造函數的類提供一個無參數的默認構造函數。這個默認構造函數將調用超類的無參構造函數。在這種情況下,如果超沒有一個無參數的構造函數,因此你必須確認它的編譯器會抱怨。如果你的類沒有明確的超類,那麼它有對象的隱式父類,其中確實有一個無參數的構造函數。

另外,在構造函數中啓動一個線程並不是一個好習慣。當你這樣做時,可能會發生一些線程競爭條件。這是更好的調用a.start()你打電話new A()後。此外,它是一種更好的圖案以定義實現Runnable代替延伸Thread的類。所以,你的代碼應該是:

class A implements Runnable() { 
    public A() { 
     // don't start it here 
    } 
    public void run() { 
     ... 
    } 
} 
... 

Thread a = new Thread(new A()); 
a.start(); 
Thread b = new Thread(new B()); 
b.start(); 
2

A延伸ThreadB延伸A,所以當你創建的A實例和B一個實例,您已經創建的Thread兩個實例。

注意,它通常優選延長Thread,而是要只是實施Runnable - 然後傳遞RunnableThread(Runnable)構造。從設計的角度來看,這最終會變得更清晰 - 你並不是真的想要改變線程行爲,你只是給它一個不同的任務來執行。

(這也是通常最好使用java.util.concurrent中,而不是直接在第一時間創建線程的設施,但我們去...)越來越創建

1

2個線程,因爲你是問爲它通過運行以下行:

A a = new A(); 
    B b = new B();