天天看點

Java線程池原理全面詳解(圖文版)

作者:mikechen的網際網路架構
Java線程池原理全面詳解(圖文版)

線程池作為一種池化技術,不僅在并發程式設計裡占據了非常重要的位置,也是大廠常問的内容了,為什麼需要線程池?線程池的流程原理?線程池有什麼風險?等等,本篇就來談談這些線程池的關鍵點@mikechen

為什麼需要線程池

在Java應用程式中,線程池是一種常見的技術,它提供了一種管理和複用線程的方式,可以顯著提高應用程式的性能和可伸縮性。

如果線程數量多的話,頻繁的建立和銷毀線程會大大浪費時間和效率,更重要的是浪費記憶體。

那麼有沒有一種方法能讓線程運作完後不立即銷毀,而是讓線程重複使用,繼續執行其他的任務哪?

有,這種方式就是線程池,線程池中的線程可以重複使用,而不是在每次需要執行任務時建立新的線程,這樣可以減少線程建立和銷毀的開銷,提高應用程式的性能。

線程池的使用風險

并不是說用了線程池就萬事大吉,其實使用線程池也是有很多風險的。

比如:同步錯誤和死鎖,還有諸如與池有關的死鎖、資源不足和線程洩漏等問題。

1.死鎖

死鎖是指兩個或多個程序在執行過程中,因争奪資源而造成的一種互相等待的現象,導緻它們都被永久阻塞,無法繼續執行下去。

死鎖的原因是資源的競争和互相等待,它通常發生在多線程并發執行的情況下,尤其是當線程需要擷取多個鎖時,如果線程之間互相等待對方釋放鎖,就會導緻死鎖的發生。

例如,線程A和線程B分别持有鎖1和鎖2,它們同時需要擷取對方持有的鎖,但是對方不釋放鎖,這時就會導緻死鎖的發生。

如下圖所示:

Java線程池原理全面詳解(圖文版)

其實:任何多線程應用程式都有死鎖風險。

2.資源不足

線程消耗包:括記憶體和其它系統資源在内的大量資源。

比如: 線程建立對象都需要記憶體空間。

除此以外,JVM 可能會為每個 Java 線程建立一個本機線程,這些本機線程将消耗額外的系統資源。

雖然線程之間切換的排程開銷很小,但如果有很多線程,環境切換也可能嚴重地影響程式的性能。

如果線程池太大,那麼被那些線程消耗的資源可能嚴重地影響系統性能。

3.線程洩漏

各種類型的線程池中一個嚴重的風險是線程洩漏,當從線程池中除去一個線程以執行一項任務,而在任務完成後該線程卻沒有傳回池時,會發生這種情況。

發生線程洩漏的一種情形出現在任務抛出一個 RuntimeException 或一個 Error 時。

如果沒有捕捉到它們,那麼線程隻會退出而線程池的大小将會永久減少一個,當這種情況發生的次數足夠多時,線程池最終就為空,而且系統将停止。

因為沒有可用的線程來處理任務。

線程池的實作原理

1.線程池組成

Java線程池主要由以下幾個部分組成:

Java線程池原理全面詳解(圖文版)
  1. 線程池管理器:負責建立和管理線程池。
  2. 工作線程:線程池中實際執行任務的線程。
  3. 任務隊列:用于存儲等待執行的任務。
  4. 任務接口:定義任務的執行方法。

2.線程池的工作原理

線程池的工作原理,如下圖所示:

Java線程池原理全面詳解(圖文版)

主要分為如下流程:

1.檢查線程池是否已滿

當一個任務需要執行時,線程池會檢查線程池中是否有空閑的線程可用,如果有,那麼一個空閑的線程會被配置設定給該任務執行。

2.将任務放入隊列

如果線程池中沒有空閑的線程可用,那麼任務會被放到任務隊列中等待執行,直到有空閑的線程可用。

3.準備開始處理任務

當一個線程完成了任務的執行後,它會傳回線程池,并且準備處理下一個任務。

4.如果已滿執行拒絕政策

如果線程池中的線程數量已經達到了限制,而且任務隊列已經滿了,那麼線程池會拒絕該任務并執行拒絕政策。

以上

更多分布式架構系列、阿裡架構師進階系列,請檢視以下文章:

阿裡架構師進階從0到1全部合集(建議收藏)

Java線程池原理全面詳解(圖文版)