多執行緒基礎知識總結
0、併發和並行、程序核線程、多程序和多執行緒的區別:
(這裡的時間和時刻上的概念同物理上的一樣)
併發:在一段時間內多個任務同時執行,或者說是在一段很短的時間內可以執行多條程式指令,微觀上看起來好像是可以同時執行多個程序,單核處理器就可以做到。
並行:在同一時刻多個任務同時執行,或者說是在同一時刻可以執行多條程式指令,多核處理器才可以做到。
程序:程序是程式的一次執行過程,是系統執行程式的基本單位,開啟 Windows 的工作管理員就可以看到很多程序。
執行緒:執行緒與程序相似,但執行緒是一個比程序更小的執行單位,一個程序在其執行的過程中可能產生多個執行緒。
多程序:每個程序都擁有自己獨立的資源,多個程序可在單核處理器上併發執行,在多核處理器上並行執行。
多執行緒:一個程序可由多個執行緒組成,多個執行緒共享程序內資源,多個執行緒可在單核處理器上併發執行,在多核處理器並行執行。
在多核處理器上,併發和並行同時存在,處理器上的每個核同一時刻同時執行多個任務,每個核在很短的時間段內又同時執行多個任務,對多工粗略劃分是多個程序,對程序劃分可能又是多個執行緒。同一時刻,處理器的每個核只能執行一個程序中的一個執行緒中的一條指令(Intel 的超執行緒技術,如雙核四執行緒,四核八執行緒,處理器的執行緒(硬體上)和程序中的執行緒(軟體上)不是一個概念,這個所謂的超執行緒技術也並不能達到真正的多核效果,只是提高了處理器的吞吐量核利用率)。
執行緒比程序更加的輕量級,程序和執行緒都是提高程式併發性和系統性能的手段,但並不是說程序越多或執行緒越多,效能越高,還要結合硬體裝置和作業系統來看。
1、建立執行緒的三種方式:
繼承 Thread 類,覆寫父類中的 run() 方法,新執行緒類建立執行緒
實現 Runnable 介面,實現介面中的 run() 方法,Thread 類建立執行緒
實現 Callable 介面,FutureTask 類構造建立方法體,Thread 類建立執行緒
3、執行緒的六種狀態:
Thread.State 列舉類中的定義
NEW:還沒開始執行的執行緒處於這種狀態
RUNNABLE:在 Java 虛擬機器中可執行的執行緒(正在執行也可能沒在執行)處於這種狀態
BLOCKED:被阻塞而等待監視鎖的執行緒處於這種狀態
WAITING:無限期的等待另一個執行緒執行特定方法的執行緒處於這種狀態
TIMED_WAITING:在指定等待時間內等待另一個執行緒執行特定的方法的執行緒處於這種狀態
TERMINATED:已經退出(執行結束)的執行緒處於這種狀態
4、執行緒的生命週期:
5、執行緒的分類:
1、普通執行緒:前臺執行緒
2、守護執行緒:
後臺執行緒,執行在後臺為其他執行緒提供服務,如果所有的前臺執行緒都死亡,後臺執行緒也自動死亡。當整個虛擬機器中只剩下後臺執行緒,虛擬機器也沒有繼續執行的必要了,虛擬機器也就退出了。
應用:JVM 虛擬機器啟動後的後臺檢測執行緒,資料庫連線池中的檢測執行緒。
最常見的守護執行緒:虛擬機器中的垃圾回收執行緒,可以通過 jconsole,jvisualvm 等工具檢視。
6、執行緒中的常用方法說明:
start():
在使用 new 關鍵字建立一個執行緒後(New 狀態),並不表現出任何的執行緒活動狀態(非 New、Terminated 狀態,可以使用 isAlive 方法檢測執行緒的活動狀態),CPU 也不會執行執行緒中的程式碼。
只有在 start() 方法執行後,才表示這個執行緒可運行了(Runnable 狀態),至於何時真正執行還要看執行緒排程器的排程。
線上程死亡後,不要再次呼叫 start() 方法。只能對新建狀態的執行緒呼叫且只能呼叫一次 start() 方法,否則將丟擲 IllegalThreadStateException 異常。
run():
啟動執行緒是 start() 方法,而不是 run() 方法。
如果直接呼叫 run() 方法,這個執行緒中的程式碼會被立即執行,多個執行緒就無法併發執行了。
join():
等待該執行緒完成的方法,其他執行緒將進入等待狀態(Waiting 狀態),通常由使用執行緒的程式(執行緒)呼叫,如將一個大問題分割為許多小問題,要等待所有的小問題處理後,再進行下一步操作。
sleep():
主動放棄佔用的處理器資源,該執行緒進入阻塞狀態(Blocked 狀態),指定的睡眠時間超時後,執行緒進入就緒狀態(Runnable),等待執行緒排程器的呼叫。
yield():
主動放棄佔用的處理器資源,執行緒直接進入就緒狀態(Runnable),等待執行緒排程器的呼叫。
可能的情況是當執行緒使用 yield 方法放棄執行後,執行緒排程器又將該執行緒排程執行。
interrupt():
沒有任何強制執行緒終止的方法,這個方法只是請求執行緒終止,而實際上執行緒並不一定會終止,在呼叫 sleep() 方法時可能會出現 InterruptedException 異常,你可能會想在異常捕獲後(try-catch語句中的catch)請求執行緒終止,而更好的選擇是不處理這個異常,拋給呼叫者處理,所以這個方法並沒有實際的用途,還有 isInterrupted() 方法檢查執行緒是否被中斷。
setDaemon():
設定守護程序,該方法必須在 start() 方法之前呼叫,判斷一個執行緒是不是守護執行緒,可以使用 isDaemon() 方法判斷。
setPriority():
設定執行緒的優先順序,理論上來說,執行緒優先順序高的執行緒更容易被執行,但也要結合具體的系統。
每個執行緒預設的優先順序和父執行緒(如 main 執行緒、普通優先順序)的優先順序相同,執行緒優先順序區間為 1~10,三個靜態變數:MIN_PRIORITY = 1、NORM_PRIORITY = 5、MAX_PRIORITY = 10。
使用 getPriority() 方法可以檢視執行緒的優先順序。
isAlive():
檢查執行緒是否處於活動狀態,如果執行緒處於就緒、執行、阻塞狀態,方法返回 true,如果執行緒處於新建和死亡狀態,方法返回 false。