1. 程式人生 > >Thread類詳解 多線程中篇(二)

Thread類詳解 多線程中篇(二)

構造 img art 身份證號 ava 概念 實例 wid 數組

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是純粹的面向對象的編程語言,什麽“封裝、繼承、多態”等等的,但是真的理解了面向對象的思維了麽?這就是面向對象!萬事萬物都是對象

Thread類詳解 多線程中篇(二)