java的多線程的概念,向來都是很複雜、籠統、抽象的。現實世界只有將知識點抽象事後纔能有效的傳播,可是傳播的過程當中,只有將抽象的知識點具象化,咱們才能習得。因此咱們會將個別內容點進行一個具象化進而解剖。當咱們理解完了以後最終將其抽象成一個個名詞:多線程、資源、鎖等。java
本文僅從如下的範圍內容來談談java的多線程。程序員
官方解釋:線程是一個單一的順序控制流程。編程
線程分主線程、子線程。由主線程來建立子線程來執行各類任務。多線程
舉例說明:以動漫「火影忍者」舉例說明,主線程就比如每個忍者,他們構成了最基本的忍者世界,一個忍者能夠按照任務的緩急、難易程度同時執行多個任務。同時忍者也能分身(調用自身查克拉)來分擔自身的任務,這就比如,忍者世界觀中的忍者主體,基本等同於程序中的主線程。主線程沒了,分身則主觀上不可控,就消失了。異步
由上圖可見,主線程與子線程的關係和忍者與分身的是很類似,也就是說,主線程能作的事,咱們都能讓子線程幫咱們作。忍者本身能作的事也能去靠分身去作。接下來,咱們來看兩段代碼。工具
//代碼一
public static void main(String[] args) {
System.out.println("Hello World!");
}
複製代碼
//代碼二
public static void main(String[] args) {
Thread thread = new Thread(()->{
System.out.println("Hello World!");
});
thread.start();
}
複製代碼
代碼一和代碼二最終的結果都是隻作了一件事,向控制檯輸出「Hello World!」。可是代碼一是由主線程去作的;代碼二是由主線程建立的子線程去作的。這裏咱們能夠看出,主線程和子線程的本質上區分並不大,由於它們都執行相同的邏輯,這一點上並無進行區分。性能
程序若是都是按照單個線程的話,那麼全部任務的執行均是按照順序來進行(串行執行)。優化
而多線程的做用是能夠安排不一樣的線程執行不一樣的任務。spa
上圖是一個理論值,咱們在某些任務密集的場景下,多線程的執行效率多數狀況下可能高於單線程的執行。線程
爲何說是可能,由於這裏建立子線程是會消耗性能的,也帶有時間消耗,若是設置不合理,單單建立子線程的時間成本就遠大於執行任務的時間成本,這一點要結合實際場景進行考慮。
舉例說明:火影裏的忍者也不會接到一批任務就立刻分身去一個個的作,他們也得結合任務的實際狀況來考慮使用分身。
java中的資源能夠理解爲,一個實例或基礎數據類型的變量的任何操做。實例或變量在這裏不能徹底算作資源,由於根據面向對象編程中的封裝性,代碼中直接將實例暴露出來給非本類的實例進行操做是一個大忌。
這裏咱們從如下資源和線程的關係進行解剖。
從這裏看,1和3沒什麼問題。由於這種機制下咱們確保了一個資源被一個線程執行(等同於一個任務被一個忍者(本體或分身都可)執行)。可是2和4就出現了一個現象,同一個資源被多個線程所操做,若是不加以控制,則會出現指定以外的執行結果或者直接產生死鎖。
舉例說明:兩個忍者都執行了同一個任務,去殺死鄰國的頭目,咱們假設忍者A過去殺死了頭目,忍者B後去的,發現頭目死了,那他接下來怎麼辦?算任務失敗仍是算完成了?
固然忍者B最後確定仍是回去覆命了,也算他任務成功,這是任務自己的規則和秩序所決定的,可是程序的世界是無秩序,須要程序員經過代碼去打造這個無序的世界從而造成秩序。
資源自身必定要包含約束性和規則性才能被正確的使用。
java自己提供了資源被多個線程調度的控制方式。
咱們經過一張圖表來概況瞭解一下。
對於資源的控制的方式無非就是一個「鎖」 字。現實當中處處充斥着這樣的例子,例如一個城市的市長,按照規定只能有一個,誰上任,那麼市長這個資源位就被誰「鎖」住了。可是程序世界中的「鎖」和現實世界中的「鎖」差異很大。
java中有關於鎖的內容很是多,咱們這裏先用一張圖來簡要介紹一下,之後再着重篇幅去介紹每一個鎖的相關特性。
用一段話形容線程和資源的關係那就是。某我的(線程)去作(調度)某件有要求和規則(鎖策略)的事(資源);根據這件事(資源)的要求和規則(鎖策略)去約束作這個事人(線程)的作法。
咱們用各類鎖策略去保證資源能被正確的使用。這裏咱們還缺一個角度,那就是從線程的角度去調度資源。
咱們用一個問題開頭來展開對話。
這就是一個線程池的雛形,線程池的雛形具備如下的基本特性
咱們來解刨線程池的最全的配置信息:
按照咱們常規的設置
BlockingQueue > maximumPoolSize ≥ corePoolSize
總結:線程池就是多個線程來調度多個資源時所優化的一種多維度的策略,它的核心就是線程的複用以及資源的緩衝存儲。
類或關鍵字 | 簡要介紹 | 使用的對象 |
---|---|---|
synchronized | 做用於方法或代碼塊中實現線程的同步性 | 資源 |
Atomic包 | 原子性控制變量或實例 | 資源 |
ReentrantLock | 做用於方法中,實現線程的同步性 | 資源 |
Semaphore | 做用於方法中,限制方法的線程最大調度數 | 資源 |
Phaser | 做用於方法中,設置線程必須調度的數量 | 資源 |
Object.wait() | 做用於同步的方法中,使當前調度的進程等待 | 資源 |
Object.notifyAll()或notify() | 做用於同步的方法中,喚起當前處於等待狀態的調度線程 | 資源 |
Runable | 線程中調度無返回結果的資源 | 線程 |
Callable | 線程中調度有返回結果的資源 | 線程 |
Future | 線程執行有返回結果的資源的接受方 | 線程 |
Executor | 建立線程池的工廠類(慎用) | 線程 |
ThreadPoolExecutor | 線程池的實現類 | 線程 |
ExecutorService | 線程池的基礎類 | 線程 |
CompletionService | 異步處理帶返回結果的線程池 | 線程 |
ScheduledExecutorService | 處理定時任務的線程池 | 線程 |
Fork-Join | 分治思想處理批量任務 | 線程 |