Java.lang.Thread是Java應用程序員對Java多線程的第一站,Thread就是對Java線程自己的抽象
因此在Java中的線程編程概念中,一個Thread實例 == 一個線程
線程有哪些屬性、行爲,Thread大體就有哪些屬性、行爲。
前文中有說到,Java線程經過Thread以及synchronized以及Object中的wait等對「控制、同步、通訊」進行了抽象,synchronized關鍵字是同步,Object中的相關方法是通訊,Thread中的信息主要是控制以及自身的行爲,可是好比join方法,也能夠被認爲是用於「通訊」,因此不要一律而論,也不要咬文嚼字,要注重背後的思惟
Thred概述
線程也是對程序運行的抽象描述,因此線程包括兩部分信息:
- 一個是線程自身數據(元數據)
- 另外一個是將要執行的任務
自身數據又分爲必備的控制信息以及行爲。
也就是說一個Thread包括了三方面的信息:基本信息、線程自身的行爲、線程任務
基本信息
以下圖所示,基本信息包括下面這些
- 名稱、id、優先級、狀態、線程組、守護線程狀態、堆棧信息跟蹤
- 上下文類加載器設置、異常處理器設置
- 是否存活、當前線程是否有權修改該線程
名稱
線程是有名稱的,有屬性name,若是不指定名稱,那麼會生成thread-0,thread-1..........thread-N這種名稱
ID
若是類比到人的話,名稱就是姓名,而ID就是身份證號,線程也有一個惟一的標識符
線程 ID 是一個正的 long 數,在建立該線程時生成,線程 ID 是惟一的,並終生不變
線程終止時,該線程 ID 能夠被從新使用
在私有方法init方法中設置
優先級
線程內部priority記錄優先級
若是設置的值不在有效範圍內,直接拋出異常
不然線程的優先級會被設置爲「指定的 newPriority 和 該線程的線程組容許的最大優先級」二者中較小的那一個。
簡單說就是不能超過線程組的最大優先級,你工資再高也超不過你領導......
線程默認的優先級是NORM_PRIORITY=5,通常狀況下不須要設置優先級
由於你設置了優先級並不必定老是徹底按照你的想法進行,前面說過,Java線程是操做系統原生線程的映射,要依賴操做系統
因此,萬萬不要業務邏輯依賴你自覺得的線程優先級
狀態
相似進程,線程也是有專門的狀態的
有內部類State
線程組
線程組用於對線程進行管理,ThreadGroup
線程組表示一個線程的集合。此外,線程組也能夠包含其餘線程組
線程組構成一棵樹,在樹中,除了初始線程組外,每一個線程組都有一個父線程組
守護線程狀態
能夠將一個Thread標記爲守護線程
守護線程,能夠認爲是後臺線程
若是沒有任何一個非守護線程在運行,或者說在運行的線程都是守護線程,JVM將退出。
全都是服務員,一個客人都沒有,那還忙活個屁?
須要注意的是,必須是線程啓動前設置,否則你試試看,分分鐘 throw new IllegalThreadStateException();
由於已啓動還沒有終止的就是isAlive==true
堆棧信息跟蹤
簡單的能夠理解爲線程運行時有一個「調用棧信息」,後續介紹
上下文類加載器設置
除非特別設置,不然contextClassLoader將會設置爲與父線程一樣的值。
上線文類加載器是類加載機制的後門,打破了雙親委派模型,此處不對上下文類加載器進行介紹,也是一個比較重要的知識點。
異常處理器設置
線程在執行單元中是不容許拋出checked異常的,並且線程運行在本身的上下文中,派生它的線程將沒法直接得到它運行中出現的異常信息。
因此Java爲咱們提供異常處理器回調機制,異常處理器的設置就是這個做用
是否存活
線程從啓動以後,直到最終終止,這一個過程被稱之爲是活動狀態
換句話說,一個線程start以後,除非他被終止,不然任什麼時候刻都是true
isAlive就是用於檢測線程是否處於活動狀態
當前線程是否有權修改該線程
斷定當前運行的線程是否有權修改該線程。
好比線程Thread aThread,在main方法中調用aThread.checkAccess,此時當前線程是主線程main,目標是aThread
那麼就是檢測主線程是否有權利修改線程aThread
線程行爲
Thread中的方法,有一些是線程自己的行爲控制或者通訊,另外還有一些至關因而工具類
還有一些被棄用了
currentThread
返回對當前正在執行的線程對象的引用,線程是Thread,哪一個Thread正在運行,那麼就返回哪一個對象就行了,返回類型就是Thread
activeCount
返回的是當前線程,所在的線程組中,活動線程的個數
enumerate
線程的抽象是Thread,每個線程都是一個Thread,既然是對象那麼就有相似尋常對象的操做,好比保存到數組
enumerate就是用來說當前線程的、所屬線程組中的、以及子組中的每個活動線程複製到指定的數組中,返回值爲複製的線程的個數
依賴於線程組中的相關方法
是否持有指定監視器的鎖
如同前面提到過的互斥量,Java中同步時須要用到一個對象鎖,若是一個線程請求的鎖被別的線程得到,那麼就須要進行等待,持有了鎖就能夠進入臨界區。
方法用於判斷當前線程,當前線程、當前線程。針對於某個對象,是否持有對應的鎖,當且僅當當前線程在指定的對象上保持監視器鎖時,才返回 true。
若是 obj 爲 null,拋出NPE
dumpStack
用於調試,將當前線程的信息打印到標準錯誤流
線程任務
線程的任務核心是Runnable,內部持有一個Runnable target,構造時若是不進行設置那麼爲null
調用start方法啓動後,會調用run方法,若是不重寫run方法,或者構造時不進程傳遞,那麼target爲null
很顯然若是target,run方法就至關於一個空方法,也就是什麼都不作。
簡言之,Java對於線程以及線程任務,進行了抽象分離,對線程的抽象爲Thread,而對於線程任務的抽象就是Runnable。
總結
Thread是Java對線程的抽象,因此他的屬性信息天然與線程的概念是不謀而合和,本文對Thread中定義的一些屬性進行了簡單介紹,有些後續還會詳細進行介紹
Thread中的方法主要用於對線程進行控制也能夠用做通訊,還有一些是基於類設計層面的,添加進來的一些工具類,能夠對線程的一些信息進行控制、獲取
線程任務是經過Runnable進行抽象,簡言之,Thread表示線程,Runnable表示任務。
「分別是爲了更好地重逢」放到這裏很是合適,解耦是爲了更好地協做。
線程自己和線程須要執行的任務進行分離,不管是從抽象概念上仍是認知理解上,亦或者是兩者獨立的發展上,解耦都有多種好處
完全認清楚Thread的本質--線程概念的抽象,纔可以更好的瞭解Thread中那些屬性字段
好比你徹底不瞭解IEEE754,何談對Float的實現熟悉?概念都不清晰,哪來的清晰地實現?
Thread是對線程的抽象,封裝了線程具備的一些屬性和狀態以及行爲信息,具體就是體如今內部的字段和方法上,另外還有一些至關於工具類的存在的方法,也是構建在Thread中的,因此線程是Thread,Thread是線程概念的體現。
無論JVM內部如何映射,操做系統如何構建線程模型,Java開發者接觸的就是Thread的實例對象。
在Java這一面向對象的語言中,多線程編程就是「多Thread對象編程」
咱們常說Java是純粹的面向對象的編程語言,什麼「封裝、繼承、多態」等等的,可是真的理解了面向對象的思惟了麼?這就是面向對象!萬事萬物都是對象