天天看點

實作并啟動線程有兩種方法

:相當于玩遊戲機,隻有一個遊戲機(cpu),可是有很多人要玩,于是,start是排隊!等cpu選中你就是輪到你,你就run(),當cpu的運作的時間片執行完,這個線程就繼續排隊,等待下一次的run()。

調用start()後,線程會被放到等待隊列,等待cpu排程,并不一定要馬上開始執行,隻是将這個線程置于可動行狀态。然後通過jvm,線程thread會調用run()方法,執行本線程的線程體。先調用start後調用run,這麼麻煩,為了不直接調用run?就是為了實作多線程的優點,沒這個start不行。

方法來啟動線程,真正實作了多線程運作。這時無需等待run方法體代碼執行完畢,可以直接繼續執行下面的代碼;通過調用thread類的start()方法來啟動一個線程, 這時此線程是處于就緒狀态, 并沒有運作。 然後通過此thread類調用方法run()來完成其運作操作的, 這裡方法run()稱為線程體,它包含了要執行的這個線程的内容, run方法運作結束, 此線程終止。然後cpu再排程其它線程。

方法當作普通方法的方式調用。程式還是要順序執行,要等待run方法體執行完畢後,才可繼續執行下面的代碼; 程式中隻有主線程——這一個線程, 其程式執行路徑還是隻有一條, 這樣就沒有達到寫線程的目的。

1.定義runnable接口的實作類,并重寫其中的run方法。run()方法的方法體是線程執行體。

2.建立runnable接口實作類的執行個體。

3.用該執行個體作為thread的target來建立thread對象。

4.調用該對象的start()方法啟動線程。

在建立thread 對象的時候可以為該thread對象指定一個名字

實作并啟動線程有兩種方法

runnable對象作為thread對象的target,runnable實作類裡面包含run方法僅僅作為執行體。也就是說thread類的作用是把run方法包裝成線程的執行體。

實際運作的線程對象依然是thread執行個體,隻是該thread線程負責執行其target的run方法。

通過jdk源碼解析thread(runable target …)調用的是哪個run方法

首先,我們來看一下jdk的thread源碼,片段 3 如下:

在run()方法中,首先會檢查target是否為空,如果不是,則執行該target的run()方法。

那麼,對于上面兩段代碼的執行,也就清楚了。

在第一個代碼段 1 中,重寫了thread的run()方法,同時傳入了一個runnable對象,該對象也實作了run()方法。該thread對象調用start()方法後,會執行該對象重寫的run()方法,其輸出結果也就是run of thread,輸出完後,run()方法傳回,該線程對象的生命周期也就結束了。

在第二個代碼段 2 中,同樣也重寫了thread的run()方法,同時傳入了一個runnable對象,實作了run()方法。唯一不同的是,在thread重寫的run方法中,在列印輸出後,還執行了super.run(),這就有意思了。

首先,該線程啟動運作後,執行其重寫的run()方法,輸出run of thread。

接下來調用super.run(),也就是調用超類的run()方法,而該超類的run()方法,也就是jdk定義的thread類的run(),其執行如上代碼段 3 所示;顯然target不為空,這時候會調用該對象的run()方法,會輸出run of runnable.。

如果,上面的thread并未重寫run()方法,那麼,執行的結果還是一樣。首先會執行該thread的run()方法,因為此時并未重寫該方法,是以還是會調用jdk定以的run()方法,也就是上面的代碼段 3,在該代碼段中會判斷target是否為空,顯然不是,是以會調用runnable對象實作的run()方法。

總結:對于thread(runnable target …),不管傳入的target是否為空,首先都會執行thread自己的run()方法。如果重寫了該方法且該方法中沒有super.run(),那麼是永遠不會調用runnable實作的run()方法;如果沒有重寫該方法,則會去判斷target是否為空,以此來決定調用target實作的run()方法;如果重寫了該方法,且該方法中有super.run(),在執行完該語句之前的所有代碼後,會判斷target是否為空,以此來決定調用target實作的run()方法,執行完後,接着執行該語句之後的代碼。