詳解Java線程池的使用及工作原理
一、什麼是線程池?
線程池是一種用於實現計算機程序並發執行的軟件設計模式。線程池維護多個線程,等待由調度程序分配任務以並發執行,該模型提高瞭性能,並避免瞭由於為短期任務頻繁創建和銷毀線程而導致的執行延遲。
二、線程池要解決什麼問題?
說到線程池就一定要從線程的生命周期講起。
從圖中可以瞭解無論任務執行多久,每個線程都要經歷從生到死的狀態。而使用線程池就是為瞭避免線程的重復創建,從而節省瞭線程的New
至Runnable
, Running
至Terminated
的時間;同時也會復用線程,最小化的節省系統資源,於此同時提高瞭響應速度。
三、線程池的使用
線程池的創建
使用ThreadPoolExecutor
並配置7個參數完成線程池的創建
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
- corePoolSize:線程池中核心線程的最大值
- maximumPoolSize:線程池中最大線程數
- keepAliveTime:非核心線程空閑的存活時間大小
- unit:keepAliveTime的單位,常用的有秒、分鐘、小時等
- workQueue:阻塞隊列類型
- threadFactory:線程工廠,用於配置線程的名稱,是否為守護線程等
- handler:線程池的拒絕策略
四、常用阻塞隊列
ArrayBlockingQueue
底層基於數組的實現的有界阻塞隊列
LinkedBlockingQueue
底層基於單鏈表的阻塞隊列,可配置容量,不配置容量默認為Integer.MAX_VALUE
五、線程工廠
在《阿裡巴巴Java開發手冊》中強制要求指定線程的名稱
由於工作是使用hutool比較多,裡面也包含對ThreadFactory
的封裝,可以很方便的指定名稱
ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build();
六、拒絕策略
當線程池內工作線程數大於maximumPoolSize時,線程就不再接受任務,執行對應的拒絕策略;目前支持的拒絕策略有四種:
1.AbortPolicy(默認):丟棄任務並拋出RejectedExecutionException
異常
2.CallerRunsPolicy:由調用者處理
3.DiscardOldestPolicy:丟棄隊列中最前面的任務,並重新入隊列
4.DiscardPolicy:丟棄任務但不拋出異常
七、線程池的執行邏輯
// 創建線程工廠 ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build(); // 創建線程池 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), threadFactory, new ThreadPoolExecutor.AbortPolicy());
八、execute()方法
// 組合值;保存瞭線程池的工作狀態和工作線程數 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
public void execute(Runnable command) { // 任務為空 拋出NPE if (command == null) throw new NullPointerException(); // 獲取線程池狀態 int c = ctl.get(); // 如果工作線程數小於核心線程數就創建新線程 if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } // 如果線程池處於Running狀態,就把任務放在隊列尾部 if (isRunning(c) && workQueue.offer(command)) { // 重新檢查線程池狀態 int recheck = ctl.get(); // 如果線程池不是Running狀態,就移除剛才添加的任務,並執行拒絕策略 if (! isRunning(recheck) && remove(command)) reject(command); // 是Running狀態,就添加線程 else if (workerCountOf(recheck) == 0) addWorker(null, false); } // 添加任務失敗,執行拒絕策略 else if (!addWorker(command, false)) reject(command); } // addWorker()完成線程的創建
九、執行流程
到此這篇關於詳解Java線程池的使用及工作原理的文章就介紹到這瞭,更多相關Java線程池內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Java線程池配置的一些常見誤區總結
- 淺談Java ThreadPoolExecutor的使用
- 一篇文章徹底搞懂jdk8線程池
- Android開發中線程池源碼解析
- Java線程池ThreadPoolExecutor源碼深入分析