摘要
為什么需要線程池呢,沒想明白這個問題,看再多線程池的源碼都沒有用,先要知道線程池技術解決了什么問題,才能看的懂源碼,因為所有的代碼都是為了解決實際的工程問題。
問題
拋幾個問題,看看你是否知道,不知道的話,可能你對線程池的理解還不夠深入,還是一知半解。那么本文會對你有用,請繼續看下去
- 線程池的線程數可以為1嗎?
- 線程數為1的線程池有存在的必要嗎
- 2個有5個核心線程的線程池和1個有10個核心線程的線程池有什么區別
- 一個應用中如何管理線程池
- 線程池池化技術和消息隊列有什么區別
線程池原理
在大學里我們學習c語言時,一個main函數寫到底,就可以交作業了。剛開始工作時,mvc一路controller -> service -> dao就OK了。但是工作中寫代碼是要解決實際問題的。你啪啪啪寫完了代碼,用戶發現你這個接口響應太慢了,怎么辦?
用戶提交任務到程序執行完成,大致的過程如上圖,提交一個task,然后有個線程去執行。
所以要提高程序執行的效率可以從兩個方面來考慮
- 異步,先響應,返回中間結果,然后異步處理,將結果返回
- 並發,多個線程來執行。
本篇說的線程池主要就是從1的維度來提高程序執行的效率
生產者消費者模式
有一定工作經驗的朋友對消息隊列的削峰填谷,系統解耦肯定不陌生。那么線程池,算不算削峰填谷呢?
異步化后,相當於把所有的task放在了隊列中。也就是生產者 -> 容器 -> 消費者。如下圖
從圖可以看出,線程池技術使系統復雜了,也提供了更多的靈活性。通過隊列的形式,我們將任務的執行拆分成了生產者,消費者模式。每一步只用關心自己的事情。如果我們的任務很復雜,我們可以將任務拆分成不同的步驟,每一步驟可以使用不同的線程池來解決,以此來提高效率。
可管理性
看上去通過線程池完美解決了我們的問題,那么需要付出什么代價呢?cpu的資源是有限的,線程的創建也需要代價
,我們一個java應用進程的資源是畢竟是有限的。我們不可能在應用中無限的創建線程池。所以我們需要管理線程池。
通常,對於簡單的應用,我們使用一個單例線程池即可,讓應用中的所有task都使用同一個線程池,防止一些初級程序員在應用中隨意創建線程池,導致線程資源吃緊,線程占用過多的資源。
當應用中task比較復雜的時候,我們就需要使用分治的思想,對線程池進行隔離。
比如有些是cpu密集型的,有些是IO密集型的;任務的重要程度也有輕重之分;任務的執行時間也有不同。我們需要對為這些任務建立不同的線程池,以此來提高效率。
總結
線程池是一種異步化技術,通過預先創建線程/異步處理來提高響應速度。同時通過統一調配線程資源,可以降低線程的重復創建問題,提高線程的利用率,中心化管理有利於對資源的有效控制,防止濫用。
關注【方丈的寺院】,與方丈一起開始技術修行之路