學習Thread線程實現原理


1:繼承Thread類創建線程

現象:創建線程的第一種方式,繼承Thread,重寫run方法,如果直接調用run方法,則和調用普通方法一樣,不會創建線程

 

 結果顯示是  main線程調用

 

 

如果調用start,是 Thread-0 調用

 

 

調用run方法,很簡單,MyThread類繼承Thread,重寫了run,所以調用run實際調用的是子類MyThread類的run,

我們來看一下start方法

 

 大致意思是:

start這個方法觸發這個線程開始執行,jvm會調用這個線程的run方法。

導致這兩個線程並發執行:當前線程調用完start就就結束了,另一個線程要執行run方法。

啟動這個線程超過1次是不合法的,尤其是線程已經執行完成不能再次被重啟。

 

我們通過注釋可以看出只有調用start方法才會創建線程,而且是准備就緒,沒有執行,具體執行需要

cpu分配時間片給該線程,這個線程只能被啟動一次,start方法上面有個synchronized鎖,應該就是控制多次啟動的。

 

 多次啟動,會報非法狀態

 

 

 來看一下start方法:

 

 

首先是判斷線程狀態,0為New新建,不是則拋異常,如果是則放入線程組,然后調用

start0方法啟動,創建該線程,創建過程設置開關,如果創建失敗則從線程組刪除

 

 

 

這個start0方法是jvm提供的方法,應該就是為線程開辟內存,分配資源等工作,具體怎么cpu怎么調到run方法的

還不知道,后面研究后 在補充 ?????????

 

來看一下run方法

 

 

 如果這個thread構建的時候以一個runnable對象作為參數,那么啟動的時候,將會調用,否則不會被調用,

當然Thread的子類應該重寫這個方法

當繼承Thread時,已經重寫run方法,所以jvm底層調用run時,其實直接調用子類的方法,而不是該方法。

 

2:實現runnable的方式創建線程

 

 

 

 

 來看一下構造Thread這個方法

new Thread(runnable);

 

 

 

 到最后把入參的target賦值給了內部維護的target變量,

 

 

 

 

所以當調用start后,創建一個線程就緒狀態,等待分配時間片。

再來看一下Thread類的run方法:

 

 因為沒有被重寫,所以會調用Thread類的run方法,target就是入參傳進來的MyRunnable對象,所以

會調用重寫的run方法。

 

3: 線程池方式創建線程

 

 

先來看一下創建線程池對象:

ExecutorService executors = Executors.newSingleThreadExecutor();

 將創建的線程池對象委托給了

FinalizableDelegatedExecutorService 對象,

 

 

 

 在這個

DelegatedExecutorService類里面,將入參委托給了ExecutorService來維護。

在回過頭來看線程池的execute方法:

 

 

 

 

然后調用到ThreadPoolExecutor方法

 

 

由於線程池里面的參數比較多,我們就假設線程池工作的線程數小於核心數:

 

 

先重點關注一下線程池的執行邏輯,具體線程池的細節可以在線程池一節在重點分析:

 

 

 

看一下new Worker(firstTask) 方法:

將runnable賦值給worker類中的變量,然后使用線程工廠創建一個線程,同時將當前worker對象作為參數傳進了線程中。

因為Worker類也實現了Runnable接口

 

 

 

 

 

由於我們創建線程時使用的是默認線程工廠:

 

 所以看一下newThread的邏輯

 

 將worker作為入參傳了進去,然后維護在Thread類中的target變量上。

 

當把worker對象放到集合workers中,添加成功后,會調用線程的start方法。

調用start方法,當cpu分配時間片給Thread時,就觸發了Worker對象的run方法

 

 

調用runWorker方法,就會調用MyRunnable方法的run方法,

 

 

就會調用我們自己實現的MyRunnable方法中。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM