0、并發和并行、進程核線程、多進程和多線程的區別:
(這里的時間和時刻上的概念同物理上的一樣)
并發:在一段時間內多個任務同時執行,或者說是在一段很短的時間內可以執行多條程序指令,微觀上看起來好像是可以同時運行多個進程,單核處理器就可以做到。
并行:在同一時刻多個任務同時執行,或者說是在同一時刻可以執行多條程序指令,多核處理器才可以做到。
進程:進程是程序的一次執行過程,是系統運行程序的基本單位,打開 Windows 的任務管理器就可以看到很多進程。
線程:線程與進程相似,但線程是一個比進程更小的執行單位,一個進程在其執行的過程中可能產生多個線程。
多進程:每個進程都擁有自己獨立的資源,多個進程可在單核處理器上并發執行,在多核處理器上并行執行。
多線程:一個進程可由多個線程組成,多個線程共享進程內資源,多個線程可在單核處理器上并發執行,在多核處理器并行執行。
在多核處理器上,并發和并行同時存在,處理器上的每個核同一時刻同時執行多個任務,每個核在很短的時間段內又同時執行多個任務,對多任務粗略劃分是多個進程,對進程劃分可能又是多個線程。同一時刻,處理器的每個核只能運行一個進程中的一個線程中的一條指令(Intel 的超線程技術,如雙核四線程,四核八線程,處理器的線程(硬件上)和進程中的線程(軟件上)不是一個概念,這個所謂的超線程技術也并不能達到真正的多核,只是盡可能的提高處理器的吞吐量核利用率)。
線程比進程更加的輕量級,進程和線程都是提高程序并發性和系統性能的手段,但并不是說進程越多或線程越多,性能越高,還要結合硬件設備和操作系統來看。
1、創建線程的三種方式:
繼承 Thread 類,覆寫父類中的 run() 方法,新線程類創建線程
實現 Runnable 接口,實現接口中的 run() 方法,Thread 類創建線程
實現 Callable 接口,FutureTask 類構造創建方法體,Thread 類創建線程
(掃一掃即可查看測試代碼)
2、三種方式的優劣:
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。