摘要:本文屬於原創,歡迎轉載,轉載請保留出處: https://github.com/jasonGeng88/blog
先來看一段代碼,咱們要建立一個固定線程池,假設固定線程數是4。代碼以下:git
Executors
是JAVA併發包中提供的,用來快速建立不一樣類型的線程池。github
是否是很簡單,建立線程池只需一行代碼。對於一些我的項目或臨時性的項目,這樣寫確實沒什麼問題,並且開發速度很快。但在一些大型項目中,這種作法通常是禁止的。併發
WHY???異步
由於用Executors
建立的線程池存在性能隱患,咱們看一下源碼就知道,用Executors
建立線程池時,使用的隊列是new LinkedBlockingQueue<Runnable>()
,這是一個無邊界隊列,若是不斷的往裏加任務時,最終會致使內存問題,也就是說在項目中因爲使用了無邊界隊列,致使的內存佔用的不可控性。下圖是不斷添加線程任務致使老年代被佔滿的狀況:性能
固然,除了內存問題,它還存在一些其餘的問題,在下面對線程池參數的介紹中會具體說明。spa
其實,問題很好解決。提供的簡便方式有侷限性,那咱們本身new一個ThreadPoolExecutor
,無非多寫幾行代碼而已。線程
關於ThreadPoolExecutor
的具體代碼以下:code
newThread(Runnable r)
建立線程的方法中,還能夠進行定製化設置,如爲線程設置特定上下文等。咱們經過一些例子,來觀察一下其內部的處理邏輯。基於上述具體代碼,咱們已經建立了一個核心線程數4,最大線程數8,線程存活時間10s,工做隊列最大容量爲10的一個線程池。blog
初始化線程池:未添加線程任務隊列
未達核心線程數:添加4個線程任務
核心線程數已滿:添加第5個線程任務
工做隊列未滿:假設添加的任務都是耗時操做(短期不會結束),再添加9個耗時任務
工做隊列已滿 & 未達最大線程數:再添加4個任務
工做隊列已滿 & 且最大線程數已滿:再添加1個任務
最後,咱們在使用線程池的時候,須要根據使用場景來自行選擇。經過corePoolSize和maximumPoolSize的搭配,存活時間的選擇,以及改變隊列的實現方式,如:選擇延遲隊列,來實現定時任務的功能。併發包Executors
中提供的一些方法確實好用,但咱們仍需有保留地去使用,這樣在項目中就不會挖太多的坑。
對於一些耗時的IO任務,盲目選擇線程池每每不是最佳方案。經過異步+單線程輪詢,上層再配合上一個固定的線程池,效果可能更好。相似與Reactor模型中selector輪詢處理