2010-05-06 70 views

回答

8

這樣你分離計算從執行(了什麼)(的時候和/或該怎麼)。

隨着RunnableCallable,你可以提交例如提交許多工作/計算Executor這將小心安排的東西。下面是摘錄形式ExecutorService

pool = Executors.newFixedThreadPool(poolSize); 
... 
pool.execute(new Handler(serverSocket.accept())); 
... 
class Handler implements Runnable { 
    ... 
} 

使用Runnable/Callable爲您提供了直接使用線程更大的靈活性。

+0

也這樣你的runnable可以擴展其他非線程類 – 2010-05-06 17:41:17

2

在繼承層次結構中擴展Thread可能沒有任何意義。如果您想修改Thread的功能,只能擴展Thread

使用Runnable,任何繼承層次結構中的任何類都可以公開可以看作是工作單元的任務,以執行Thread

3

因爲IS-A真的不是你想要的。你的班級希望成爲Runnable,但IS-A Thread感覺太強大了。這就是繼承所說的。你真的只想實現run()方法,而不是Thread類中的所有其他關注點。

這符合Scott Meyers在「更有效的C++」中的非常好的建議:使非葉類抽象化。替代接口,你就會發現。

18

實際的問題是,在任何有問題的情況下,implements總是優先於延伸。

Extends綁定兩個類文件非常密切,可能會導致一些很難處理代碼。

當我第一次「理解」OO編程時,我擴展了一切,但它將我的整個設計變成了一團糟。現在我僅僅擴展幾件事情,明確而明顯地通過了「is-a」測試,其他一切都是一個接口...

許多問題剛剛停止發生(混淆多重繼承情況,浪費時間浪費重構層次結構,傾向於有「保護」變量,然後想知道爲什麼他們正在改變,當你沒有改變他們在當前的類,鏈接需求的構造函數,弄清楚如何不同的繼承樹互相交互,...

它似乎每3年(過去20年),我認爲我真的「獲得」編程,並回顧3年前我做的蠢事......這是其中的一個實例(但接近7年前在這一點上)

2

爲什麼你可能更喜歡實施Interface Runnable以延長Class Thread的原因有以下幾點:

  • 更少的開銷在一個序貫上下文(source

當你繼承Thread類,每個線程的創建獨特 OBJ並與之相關聯。當你實現Runnable時,它將同一個對象分享給多個線程。

來源:a blog - 我不太清楚,如果這是正確的

  • 可以發送任務,在與Runnable接口網絡(線程不是序列化的,source
  • 更好OOP風格
    • 這很可能是你沒有「是」的關係
    • 必須擴展其他類的可能性(Java沒有多重繼承)
0

要回答這個問題首先:

如果延長線,您的類(延長線)的實例將始終調用超類線程的構造函數。所以 MyClass myclass = new MyClass() 將在MyClass的構造函數中總是調用「super()」來實例化一個線程,最後你可以在你的類中實現一些開銷(如果你不使用任何方法超類線程)。因此只實現Runnable可以讓你的類運行得更快而沒有任何繼承開銷。

此外,這裏還有一些錯誤的答案:

現在我剛好延伸的幾件事情,清楚,明顯傳遞「是一個」測試和其他一切是一個接口...

你有沒有想過創建一個沒有任何接口的對象?因爲爲每個對象實現一個接口是非常錯誤的!

擴展Thread類時,每個線程都會創建唯一對象並與其關聯。當你實現Runnable時,它將共享同一個對象給多個線程。

錯,每次調用類的構造函數時,都會得到一個自己的對象,從擴展位置或實現的位置無關緊要!在Java中,EVERY類實例是一個對象,並且擴展了Object類(儘管原語不是...)。只有像int []類這樣的基元數組可以擴展Object,並且這種數組具有與任何對象相同的方法 - 但是在Javadoc中並沒有提到它們!太陽傢伙可能不希望我們使用它們)。

順便說一句,至少有兩個繼承的優點:代碼共享和清晰的Javadoc。因爲如果你從一個類繼承,你可以看到Javadoc中的所有子類。你也可以通過界面來做到這一點,但是你不能共享代碼。更重要的是,您需要創建「嵌套」對象並調用兩個或更多對象的構造函數,而不是僅調用一個對象,這又意味着您需要從超類對象本身實現一些開銷!因爲Java中沒有對象而沒有開銷,並且創建儘可能少的對象對於高性能應用程序非常重要。對象是最偉大的東西,但不必要的對象不是...

相關問題