ThreadPoolExecutor使用和思考(中)-keepAliveTime及拒絕策略
工作中多處接觸到了ThreadPoolExecutor。趁著現在還算空,學習總結一下。
前記:
- jdk官方文件(javadoc)是學習的最好,最權威的參考。
- 文章分上中下。上篇中主要介紹ThreadPoolExecutor接受任務相關的兩方面入參的意義和區別,池大小引數corePoolSize和maximumPoolSize,BlockingQueue選型(SynchronousQueue,
LinkedBlockingQueue,
ArrayBlockingQueue
);中篇中主要聊聊與keepAliveTime這個引數相關的話題;下片中介紹一下一些比較少用的該類的API,及他的近親:ScheduledThreadPoolExecutor。 - 如果理解錯誤,請直接指出。
===============================神奇分割線==================================
通過上篇文章,我們可以總結出:ThreadPoolExecutor中額定的“工人”數量由corePoolSize決定,當任務數量超過額定工人數量時,將任務快取在BlockingQueue之中,當發現如果連queue中也放不下時(可能是因為使用有界queue,也可能是使用SynchronousQueue),ThreadPoolExecutor會請求“老闆”再派幾個“工人”過來。
接下來發生的事情有兩種情況:
- 任務不再過來了 - keepAliveTime
- 任務仍然繼續過來 - RejectedExecutionHandler
===============================神奇分割線==================================
keepAliveTime
jdk中的解釋是:當執行緒數大於核心時,此為終止前多餘的空閒執行緒等待新任務的最長時間。
有點拗口,其實這個不難理解,在使用了“池”的應用中,大多都有類似的引數需要配置。比如資料庫連線池,DBCP中的maxIdle,minIdle引數。
什麼意思?接著上面的解釋,後來向老闆派來的工人始終是“借來的”,俗話說“有借就有還”,但這裡的問題就是什麼時候還了,如果借來的工人剛完成一個任務就還回去,後來發現任務還有,那豈不是又要去借?這一來一往,老闆肯定頭也大死了。
合理的策略:既然借了,那就多借一會兒。直到“某一段”時間後,發現再也用不到這些工人時,便可以還回去了。這裡的某一段時間便是keepAliveTime的含義,TimeUnit為keepAliveTime值的度量。
RejectedExecutionHandler
另一種情況便是,即使向老闆借了工人,但是任務還是繼續過來,還是忙不過來,這時整個隊伍只好拒絕接受了。
RejectedExecutionHandler介面提供了對於拒絕任務的處理的自定方法的機會。在ThreadPoolExecutor中已經預設包含了4中策略,因為原始碼非常簡單,這裡直接貼出來。
CallerRunsPolicy:執行緒呼叫執行該任務的 execute 本身。此策略提供簡單的反饋控制機制,能夠減緩新任務的提交速度。
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- if (!e.isShutdown()) {
- r.run();
- }
- }
這個策略顯然不想放棄執行任務。但是由於池中已經沒有任何資源了,那麼就直接使用呼叫該execute的執行緒本身來執行。
AbortPolicy:處理程式遭到拒絕將丟擲執行時
RejectedExecutionException
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- throw new RejectedExecutionException();
- }
這種策略直接丟擲異常,丟棄任務。
DiscardPolicy:不能執行的任務將被刪除
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- }
這種策略和AbortPolicy幾乎一樣,也是丟棄任務,只不過他不丟擲異常。
DiscardOldestPolicy:如果執行程式尚未關閉,則位於工作佇列頭部的任務將被刪除,然後重試執行程式(如果再次失敗,則重複此過程)
- public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- if (!e.isShutdown()) {
- e.getQueue().poll();
- e.execute(r);
- }
- }
該策略就稍微複雜一些,在pool沒有關閉的前提下首先丟掉快取在佇列中的最早的任務,然後重新嘗試執行該任務。這個策略需要適當小心。
設想:如果其他執行緒都還在執行,那麼新來任務踢掉舊任務,快取在queue中,再來一個任務又會踢掉queue中最老任務。
總結:
keepAliveTime和maximumPoolSize及BlockingQueue的型別均有關係。如果BlockingQueue是無界的,那麼永遠不會觸發maximumPoolSize,自然keepAliveTime也就沒有了意義。
反之,如果核心數較小,有界BlockingQueue數值又較小,同時keepAliveTime又設的很小,如果任務頻繁,那麼系統就會頻繁的申請回收執行緒。
相關文章
- 執行緒池ThreadPoolExecutor裡面4種拒絕策略執行緒thread
- ThreadPoolExecutor執行緒池的keepAliveTimethread執行緒
- Java 執行緒池四種拒絕策略Java執行緒
- 拒絕使用 rm -rf 命令 ?
- 部署SDN:拒絕誘惑認真思考企業需求
- 知道執行緒池的四種拒絕策略嗎?執行緒
- MacBook上使用ssh localhost被拒絕Maclocalhost
- Java執行緒池8大拒絕策略,面試必問!Java執行緒面試
- 專案管理中學會拒絕(轉)專案管理
- 拒絕遊戲創業遊戲創業
- ThreadPoolExecutor的使用及原始碼分析thread原始碼
- python中ThreadPoolExecutor如何使用Pythonthread
- Spring Boot中如何配置執行緒池拒絕策略,妥善處理好溢位的任務Spring Boot執行緒
- 慢速 HTTP 拒絕服務: 分析利用和緩解HTTP
- 分散式拒絕服務攻擊(DDoS)原理及防範分散式
- 程式被拒絕的原因
- ELK實驗中 顯示連線拒絕訪問
- PR如何在專案管理中學會拒絕?(轉)專案管理
- 遊戲美宣,拒絕亂穿衣遊戲
- PhpMyAdmin訪問被拒絕PHP
- RabbitMQ-訊息永續性、確認機制、拒絕、預取數量、分配策略MQ
- Ubuntu ssh伺服器拒絕密碼(使用root登入)Ubuntu伺服器密碼
- ThreadPoolExecutor的應用和實現分析(續)—— 任務飽和丟棄策略thread
- websocket連線mina被拒絕Web
- Apache 拒絕分割下載請求…Apache
- Google拒絕前員工幫助Go
- 記錄曾經拒絕的話
- 【2017年蘋果過審指南】十大常見被拒原因及拒絕跳坑祕籍蘋果
- 印表機拒絕訪問是什麼問題 win10共享印表機拒絕訪問Win10
- Mac電腦使用:你無法拒絕的Mac觸發角Mac
- 執行緒池(詳解):三大方法、七大引數、四種拒絕策略執行緒
- 面試官問:執行緒池除了常見的4種拒絕策略,你還知道哪些?面試執行緒
- Torvalds 拒絕接受 ZFS 檔案系統
- localhost拒絕訪問的解決方法localhost
- 遊戲主機:拒絕逝去的“恐龍”遊戲
- iOS稽核拒絕蘋果官方原因詳解iOS蘋果
- 探祕PHP拒絕服務攻擊PHP
- 不可變基礎設施:拒絕 SSH