1.背景
线程池在执行任务过程中,往往由于个别耗时非常大的任务导致任务积压,影响性能,甚至导致系统崩溃,可以通过监控每个任务执行的耗时来提前预警,进而优化代码,使系统更稳定。
2.实现代码
实现原理:继承ThreadPoolExecutor,重写beforeExecute,在开始的时候记录开始时间,然后重写afterExecute,在结束的时候计算耗时。
package com.xkzhangsan.thread.pool.monitor; import com.xkzhangsan.thread.pool.monitor.constant.MonitorLevelEnum; import java.util.Date; import java.util.List; import java.util.concurrent.*; /** * 线程池监控器 <br> * 支持监控基本情况和任务执行情况<br> * @author xkzhangsan */ public class ThreadPoolMonitor extends ThreadPoolExecutor { private String poolName; private MonitorLevelEnum monitorLevel; private ConcurrentHashMap<String, Date> taskStartTimeMap; public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); } public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); } public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); } public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); } //overload public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, String poolName, MonitorLevelEnum monitorLevel) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); init(poolName, monitorLevel); } public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, String poolName, MonitorLevelEnum monitorLevel) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); init(poolName, monitorLevel); } public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler, String poolName, MonitorLevelEnum monitorLevel) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); init(poolName, monitorLevel); } public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler, String poolName, MonitorLevelEnum monitorLevel) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); init(poolName, monitorLevel); } @Override protected void beforeExecute(Thread t, Runnable r) { if (monitorLevel == MonitorLevelEnum.TASK || monitorLevel == MonitorLevelEnum.POOL_TASK || monitorLevel == MonitorLevelEnum.SUGGESTION) { //TODO 增加线程名称 taskStartTimeMap.put(String.valueOf(r.hashCode()), new Date()); } } @Override protected void afterExecute(Runnable r, Throwable t) { if (monitorLevel == MonitorLevelEnum.TASK || monitorLevel == MonitorLevelEnum.POOL_TASK || monitorLevel == MonitorLevelEnum.SUGGESTION) { Date date = taskStartTimeMap.remove(String.valueOf(r.hashCode())); if (date == null) { return; } System.out.println("poolName:" + poolName + " task:" + r.hashCode() + " cost:" + ((new Date()).getTime() - date.getTime())); } } @Override public void shutdown() { super.shutdown(); } @Override public List<Runnable> shutdownNow() { return super.shutdownNow(); } private void init(String poolName, MonitorLevelEnum monitorLevel) { this.poolName = poolName; this.monitorLevel = monitorLevel; this.taskStartTimeMap = new ConcurrentHashMap<>(); } }
package com.xkzhangsan.thread.pool.monitor.constant; /** * 线程池监控级别 <br> * @author xkzhangsan */ public enum MonitorLevelEnum { /** * 不监控,默认值 */ NONE, /** * 监控基本信息 */ POOL, /** * 监控任务信息 */ TASK, /** * 同时监控基本信息和任务信息 */ POOL_TASK, /** * 同时监控基本信息和任务信息,并给出优化建议 */ SUGGESTION; }
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) { taskMonitor(); } public static void taskMonitor() { ThreadPoolMonitor threadPoolMonitor = new ThreadPoolMonitor(1, 3, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5), "test", MonitorLevelEnum.TASK); for (int i = 0; i < 5; i++) { int finalI = i; threadPoolMonitor.execute(() -> { try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(finalI); }); } threadPoolMonitor.shutdown(); } }
3.2 测试结果
0 poolName:test task:338537012 cost:3012 1 poolName:test task:451561153 cost:3008 2 poolName:test task:517325124 cost:3001 3 poolName:test task:1540836602 cost:3004 4 poolName:test task:575812030 cost:3010
源代码地址:https://github.com/xkzhangsan/thread-pool-monitor标签:maximumPoolSize,poolName,int,keepAliveTime,monitorLevel,任务,线程,监控,workQueue From: https://www.cnblogs.com/xkzhangsanx/p/18430001
参考:https://cloud.tencent.com/developer/article/1491221