1.實現原理
這篇博文是基於執行緒池監控1-監控任務執行時間,原理是:建立一個固定時間間隔執行的執行緒,來記錄執行緒池的池狀態、執行緒數量和佇列任務數量等,具體方案:使用單例類快取所有建立的執行緒池物件,類建立時啟動定時任務執行緒,定期遍歷快取中執行緒池,記錄執行緒池資訊。
2.實現程式碼
package com.xkzhangsan.thread.pool.monitor; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 全域性監控 <br> * 1.定期記錄執行緒池基本資訊 <br> * * @author xkzhangsan */ public class GlobalMonitor { private static volatile GlobalMonitor instance; private static final ConcurrentHashMap<String, ThreadPoolMonitor> threadPoolMonitorMap = new ConcurrentHashMap<>(); private static final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); private GlobalMonitor() { scheduledThreadPoolExecutor.scheduleAtFixedRate(new PoolInfoRunnable(), 10, 10, TimeUnit.SECONDS); } public static GlobalMonitor getInstance() { if (instance == null) { synchronized (GlobalMonitor.class) { if (instance == null) { instance = new GlobalMonitor(); } } } return instance; } public void put(String poolName, ThreadPoolMonitor threadPoolMonitor) { threadPoolMonitorMap.put(poolName, threadPoolMonitor); } public void remove(String poolName) { threadPoolMonitorMap.remove(poolName); } static class PoolInfoRunnable implements Runnable { @Override public void run() { threadPoolMonitorMap.forEach((poolName, threadPoolMonitor) -> { int currentPoolSize = threadPoolMonitor.getPoolSize(); int queueSize = threadPoolMonitor.getQueue().size(); System.out.println("poolName:" + poolName + " status:" + threadPoolMonitor.getStatus() + " corePoolSize:" + threadPoolMonitor.getCorePoolSize() + " maximumPoolSize:" + threadPoolMonitor.getMaximumPoolSize() + " currentPoolSize:" + currentPoolSize + " queueCapacity:" + threadPoolMonitor.getQueueCapacity() + " queueSize:" + queueSize); }); } } }
獲取執行緒池狀態
這裡參考了ThreadPoolExecutor的toString(),返回Running、Shutting down、Terminated 三種狀態。
見:ThreadPoolMonitor類
public String getStatus() { if (super.isTerminated()) { return "Terminated"; } else if (super.isShutdown()) { return "Shutting down"; } else { return "Running"; } }
獲取佇列總容量
建立ThreadPoolExecutor時,傳入的BlockingQueue<Runnable> workQueue,無法直接獲取總容量,ThreadPoolExecutor又沒有直接獲取總容量的方法,
這裡想到另一個方法,Queue的remainingCapacity()返回當前佇列剩餘容量,原理:總容量-佇列size,所以,在剛建立時size為0,返回的就時總容量。
見:ThreadPoolMonitor類
private void init(String poolName, MonitorLevelEnum monitorLevel) { this.poolName = poolName; this.monitorLevel = monitorLevel; this.taskStartTimeMap = new ConcurrentHashMap<>(); if (isPoolMonitor()) { GlobalMonitor.getInstance().put(poolName, this); } this.queueCapacity = super.getQueue().remainingCapacity(); } public int getQueueCapacity() { return this.queueCapacity; }
3.測試執行
3.1 測試程式碼
package com.xkzhangsan.thread.pool.monitor; import com.xkzhangsan.thread.pool.monitor.constant.MonitorLevelEnum; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeUnit; public class ThreadPoolMonitorTest { public static void main(String[] args) throws InterruptedException { poolMonitor(); } public static void poolMonitor() throws InterruptedException { ThreadPoolMonitor threadPoolMonitor = new ThreadPoolMonitor(1, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(1000), "test", MonitorLevelEnum.POOL); for (int i = 0; i < 100; i++) { int finalI = i; threadPoolMonitor.execute(() -> { try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(finalI); }); } //因為呼叫shutdown方法會將threadPoolMonitor從監控快取中刪除,這裡sleep 100s TimeUnit.SECONDS.sleep(100); //執行緒池必須手動關閉,否則一直執行 threadPoolMonitor.shutdown(); } }
3.2 測試結果
0 1 2 poolName:test status:Shutting down corePoolSize:1 maximumPoolSize:3 currentPoolSize:1 queueCapacity:1000 queueSize:96 3 4 5 poolName:test status:Shutting down corePoolSize:1 maximumPoolSize:3 currentPoolSize:1 queueCapacity:1000 queueSize:93 6 7 8 poolName:test status:Shutting down corePoolSize:1 maximumPoolSize:3 currentPoolSize:1 queueCapacity:1000 queueSize:90 9
執行緒sleep 3s,監控日誌10s列印一次,佇列中的任務在不斷被消費減少。
原始碼地址:https://github.com/xkzhangsan/thread-pool-monitor
https://gitee.com/xkzhangsan/thread-pool-monitor