Thread線程原理解析

1、構造函數

在這裏插入圖片描述

2、啓動線程

啓動線程很簡單,只需要new Thread,實現run方法,調用start即可以啓動線程
在這裏插入圖片描述

3、構造函數深入

Thread線程的構造函數很多,但最終都會進入到該初始化方法中
在這裏插入圖片描述

3.1、線程組

ThreadGroup g:線程組,如果不指定,則默認使用父線程的線程組
在這裏插入圖片描述
在這裏插入圖片描述
發現兩個線程的線程組結果都是‘main’線程

3.2、Runnable

Runnable target:run的業務實現體,start將會調用對象的run方法,如果target==null,即該線程的實現爲空,則不會執行。(開闢線程只有Thread一種,Runnable、Callable、線程池都是需要Thread去構造start去啓動線程
在這裏插入圖片描述

3.2、線程名稱

String name:線程的名稱,如果不指定則默認以‘Thread-從0開始的計數器’爲名稱。
在這裏插入圖片描述
而計數器則是以static標識的int類型,即加載Thread類的時候只會初始化一次計數器,之後創建的線程則會累加。
在這裏插入圖片描述

3.3、線程棧深度

long stackSize:新線程的堆棧空間大小,默認爲0,表示忽略該參數,同時又是與平臺相關的。
在這裏插入圖片描述
如圖代碼中,線程中run調用了一個遞歸方法,一直累加計數,結果如下圖,棧溢出。main線程是JVM虛擬機自動開闢的線程,stackSize我們指定不了。
在這裏插入圖片描述
而什麼是棧溢出呢?當我們執行迭代方法時,進入一次方法就會壓一次棧,直到棧超出了指定的棧深度。如果不使用迭代,而只是簡單的累加,則不會有任何情況發生。
在這裏插入圖片描述
如果stackSize過高:超過JVM,則爲JVM最大值,同時存活的線程數低。
如果stackSize過低:低於JVM,則爲JVM最小值,同時存活的線程數高。
且過高過低會導致平臺可能不支持該參數。

3.4、AccessControlContext

默認值爲AccessController.getContext(),返回的類爲AccessControlContext,該類是一個對security權限上下文進行了封裝的一個類,能夠對資源進行決策是否有權限。

該類有衆多方法,但對權限上下文封裝的public方法只有一個:
在這裏插入圖片描述
從方法名字看,是對系統某些保護的權限(context)進行檢測是否有權限,如果沒有權限,則會拋出AccessControlException權限不足的異常。在AccessControlContext的checkPermission方法中:
在這裏插入圖片描述

3.5、inheritThreadLocals

是否繼承父線程的ThreadLocals:默認是true,在初始化線程時,默認會執行ThreadLocal.createInheritedMap去繼承父線程的ThreadLocals。
在這裏插入圖片描述
繼續追蹤,找到了關鍵的幾行代碼,將父線程的ThreadLocalMap的table賦值到本線程中,且對父線程所有的ThreadLocal進行childValue處理(此處只是直接將值返回,只是方法名易於區分),將新的值從新賦值到table中。
在這裏插入圖片描述
主要作用是將父線程的信息進行傳遞給子線程。

3.6、構造函數中的其它處理

daemon線程:默認繼承父類的守護線程,如果父類不是守護線程,則通過在調用start前設置setDaemon(true),當系統中只剩下守護線程時會自動退出。

priority優先級:默認繼承父類的線程優先級,設置後線程執行時,CPU會優先執行該線程邏輯(不一定,只是概率高了,執不執行還得看CPU臉色啊!)

tid線程id:由 tid = nextThreadID();創建,該值爲系統static變量,且唯一。

4、start原理

當構造完一個線程後,線程不會立即被創建,而是要調用線程對象的start方法。調用後會將threadStatus變量更改,如果啓動後任然調用start方法,則會拋出IllegalThreadStateException異常
在這裏插入圖片描述
在這裏插入圖片描述
此時纔是開闢線程的關鍵代碼
在這裏插入圖片描述
線程啓動需要調用start()方法,內部調用了start0()方法,該方法爲本地方法區代碼,由JVM自動調用,最終會執行Runnable的run方法
在這裏插入圖片描述在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章