三 Java多線程-ThreadPool線程池

開完一趟車完整的過程是啟動、行駛和停車,但老司機都知道,真正費油的不是行駛,而是長時間的怠速、頻繁地踩剎車等動作 。因為在速度切換的過程中,發送機要多做一些工作,當然就要多費一些油 。
而一個Java線程完整的生命周期就包括:

1、T1:創建(啟動)
2、T2:運行(行駛)
3、T3:銷毀(停車)
而T1 + T3的開銷(汽油或者時間)是要遠大于T2的 。所以,即使是性能再好的車,或者性能再好的計算機,如果經常有T1 + T3的操作存在 , 那么顯然是扛不住的 。
所以,為了解決這種因為切換不同線程導致的效率問題,Java推出了線程池技術 。通過對已創建線程的合理重用,既能解決上述問題,又能進一步提高響應速度 , 提升系統性能和穩定性 。線程池特別適合下面的應用場景:
1、單個任務處理時間較短
2、需要處理的任務數量大
比如硬件數據采集,像手機、車載和安防傳感器的數據采集就特別符合這種情況 。
這是線程池相關繼承結構圖:
三 Java多線程-ThreadPool線程池

文章插圖
很多人都分不清Executor和Executors這兩個東西:Executor是接口,是一個根據一組執行策略調用、調度、執行和控制的異步任務框架,提供了一種將“任務提交”與“任務如何運行”分離開的機制 。而Executors則是一個工具類(不用new),提供了諸多用于線程池的靜態方法 。Executor和Executors的關系,和Java I/O中Collection和Collections的關系一毛一樣 。所以下次再看到XXX和XXXs的時候應該就知道Java的調性了 。
說起來還是有點枯燥,那么我拿之前做的一個例子來說一下就明白了 。
假設有一個工地有若干項目經理和工人,1個經理+1個工人組成工作小隊,工地有很多個這樣的工作小隊,這些工作小隊需要加入項目組,但是只有有活干的才能加入,沒活干的加不了,就能要被優化裁員 。
/** * 工人 */public class Worker {/*** 干活*/public void dosomething() {try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("挖坑");}}/** * 經理 */public class Manager implements Runnable {private Worker worker;public Worker getWorker() {return worker;}public void setWorker(Worker worker) {this.worker = worker;}/*** 經理動嘴,工人動手*/@Overridepublic void run() {worker.dosomething();}}/** * 項目組 */public class ManagerGroup {private static ExecutorService projectGroup = new ThreadPoolExecutor(3, // 核心小隊數量3, // 最多能容納多少個小隊30, // 多久沒活干就請出項目組TimeUnit.SECONDS, // 時間單位new ArrayBlockingQueue<Runnable>(3),// 有多少個項目經理就不再接收入組申請new ThreadPoolExecutor.CallerRunsPolicy() // 項目組拒絕響應時怎么處理);// 項目組增加工作小隊public static void addTask(Manager manager) {projectGroup.execute(manager);}public static void main(String[] args) {Manager manager1 = new Manager();Worker worker1 = new Worker();manager1.setWorker(worker1);Manager manager2 = new Manager();Worker worker2 = new Worker();manager2.setWorker(worker2);Manager manager3 = new Manager();Worker worker3 = new Worker();manager3.setWorker(worker3);// 申請進入項目組有活干才可能不被優化ManagerGroup.addTask(manager1);ManagerGroup.addTask(manager2);ManagerGroup.addTask(manager3);}}可以自己將核心小組數量、最多能容納的小隊數量等數字調節一下 , 然后運行看看效果 。
和線程一樣,線程池也有自己的狀態,而且和線程的狀態差不多(想想也是 , 畢竟要符合線程生命周期的東西,確實應該差不多) 。線程池狀態:
三 Java多線程-ThreadPool線程池

文章插圖
1、RUNNING:正常運行,能接收新任務,也能處理阻塞隊列中的任務;
2、SHUTDOWN:關閉狀態,不接收新任務,但可以繼續處理阻塞隊列中已有任務;
3、STOP:既不接收新任務,也不處理隊列中的任務 , 并會中斷正在處理的任務;
4、TIDYING(這個名字叫得有點奇怪):如果所有任務都已中止 , 且workCount有效線程數為0,則會調用terminated()方法進入TERMINATED狀態;
5、TERMINATED:terminated()方法執行完后進入該狀態,什么也不做 。
線程池運行時的流程圖:
三 Java多線程-ThreadPool線程池

文章插圖
至于線程池的構造函數什么的就不多啰嗦了,太枯燥無聊 。
【三 Java多線程-ThreadPool線程池】

推薦閱讀