徹底理解Runnable和Thread的區別

2021-09-25 16:32:14 字數 3218 閱讀 5933

《elasticsearch權威指南》

在實際工作中,我們很可能習慣性地選擇runnable或thread之一直接使用,根本沒在意二者的區別,但在面試中很多自以為是的菜貨面試官會經常而且非常嚴肅的問出:請你解釋下runnable或thread的區別?尤其是新手就容易上當,不知如何回答,就胡亂編一通。鄙人今天告訴你們這二者本身就沒有本質區別,就是介面和類的區別。問出這個問題的面試官本身就是個二流子!如果非要說區別,請看如下:

runnable的實現方式是實現其介面即可

thread的實現方式是繼承其類

runnable介面支援多繼承,但基本上用不到

thread實現了runnable介面並進行了擴充套件,而thread和runnable的實質是實現的關係,不是同類東西,所以runnable或thread本身沒有可比性。

網路上流傳的最大的乙個錯誤結論:runnable更容易可以實現多個執行緒間的資源共享,而thread不可以!這是乙個二筆的結論!網路得出此結論的例子如下:

//program--thread

public class test

static class mythread extends thread}}

}}

執行結果如下:

thread ticket = 5

thread ticket = 5

thread ticket = 4

thread ticket = 3

thread ticket = 2

thread ticket = 1

thread ticket = 0

thread ticket = 4

thread ticket = 3

thread ticket = 2

thread ticket = 1

thread ticket = 0

process finished with exit code 0

很顯然,總共5張票但賣了10張。這就像兩個售票員再賣同一張票,原因稍後分析。現在看看使用runnable的結果:

//program--runnable

public class test2

static class mythread2 implements runnable}}

}}

執行結果如下:

runnable ticket = 5

runnable ticket = 4

runnable ticket = 3

runnable ticket = 1

runnable ticket = 0

runnable ticket = 2

process finished with exit code 0

嗯,嗯,大多數人都會認為結果正確了,而且會非常鄭重的得出:runnable更容易可以實現多個執行緒間的資源共享,而thread不可以!真的是這樣嗎?大錯特錯!

program–thread這個例子結果多賣一倍票的原因根本不是因為runnable和thread的區別,看其中的如下兩行**:

new mythread().start();

new mythread().start();

例子中,建立了兩個mythread物件,每個物件都有自己的ticket成員變數,當然會多賣1倍。如果把ticket定義為static型別,就離正確結果有近了一步(因為是多執行緒同時訪問乙個變數會有同步問題,加上鎖才是最終正確的**)。

現在看program–runnable例子中,如下**:

mythread2 mt=new mythread2();

new thread(mt).start();

new thread(mt).start();

只建立了乙個runnable物件,肯定只賣一倍票(但也會有多執行緒同步問題,同樣需要加鎖),根本不是runnable和thread的區別造成的。再來看乙個使用thread方式的正確例子:

public class test3  extends thread  catch (interruptedexception e) }}

}}

public static void main(string arg)

}

執行結果如下:

執行緒1賣票---->10

執行緒1賣票---->9

執行緒1賣票---->8

執行緒1賣票---->7

執行緒1賣票---->6

執行緒1賣票---->5

執行緒1賣票---->4

執行緒1賣票---->3

執行緒1賣票---->2

執行緒1賣票---->1

process finished with exit code 0

上例中只建立了乙個thread物件(子類test3),效果和runnable一樣。synchronized這個關鍵字是必須的,否則會出現同步問題,篇幅太長本文不做討論。

上面討論下來,thread和runnable沒有根本的沒區別,只是寫法不同罷了,事實是thread和runnable沒有本質的區別,這才是正確的結論,和自以為是的大神所說的runnable更容易實現資源共享,沒有半點關係!

現在看下thread原始碼:

public

class thread implements runnable

private volatile string name;

private int priority;

private thread threadq;

private long eetop;

可以看出,thread實現了runnable介面,提供了更多的可用方法和成員而已。

結論,thread和runnable的實質是繼承關係,沒有可比性。無論使用runnable還是thread,都會new thread,然後執行run方法。用法上,如果有複雜的執行緒操作需求,那就選擇繼承thread,如果只是簡單的執行乙個任務,那就實現runnable。

再遇到二筆面試官問thread和runnable的區別,你可以直接鄙視了!

Callable和Runnable用法和比較

比較 callable有返回值並且可以拋異常 runnable無返回值並且不能拋異常。futuretask和future future 介面,用於獲得任務的執行結果。future的get方法獲取結果只有在計算完成時獲取,否則會一直阻塞直到任務轉入完成狀態,然後會返回結果或者丟擲異常。futureta...

徹底理解sizeof

很多人認為sizeof是乙個函式,這是從它的用法看出來的,因為我們用的時候一般會寫成sizeof 確實像函式。但sizeof其實是操作符,返回乙個物件或者型別在當前平台下所佔的記憶體位元組數。首先我們來看乙個例子,注意本機使用平台為64位系統 includeint main void 輸出結果是 1...

徹底理解多型

父類引用或者介面的引用指向了自己的子類物件。animal a new cat 父類可以呼叫子類中覆寫過的 父類中有的方法 多型的好處 提高了程式的擴充套件性。繼承的父類或介面一般是類庫中的東西,如果要修改某個方法的具體實現方式 只有通過子類去覆寫要改變的某乙個方法,這樣在通過將父類的應用指向子類的例...