线程池监控2-监控线程池状态、线程数量和队列任务数量等

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


发表评论

评论已关闭。

相关文章