线程池监控 - 简易版

  Java线程池想必大家都不会陌生,对于一些可以并发可以执行的任务,我们优先选择考虑线程池进行操作,但是对于其中一些指标出问题,我们很难去排查,这里就带大家撸一个简易版本的线程池监控。

ThreadPoolExecutor

  在原生的线程池中,许多我们想监控的变量都是private的(满满的恶意),但是有些是提供了get方法帮助我们去获取(除了运行状态字段)。

  我们要想完成达到监控的效果,就要对此进行扩展,不满足于只有get方法的字段监控。这个时候就需要介绍下原生线程池中的两个方法:

  1. beforeExecute(Thread t, Runnable r)

    该方法是执行任务之前执行。
  2. afterExecute(Runnable r, Throwable t)

    该方法是执行任务之后执行(必执行,放置在finally语句中)。

我们可以在这两个方法中增加额外操作,帮助我们可以监控其他指标。

MBean

  MBean就是一种规范的JavaBean,通过集成和实现一套标准的Bean接口,这种叫MBean,Mbean注册到MBeanServer中。(可以理解为一种JVM允许状态辅助查询的Bean)。

  在本Demo中,我是通过MBean的形式去进行指标的监控,所以也帮大家去了解下它。

  在此,我使用的HtmlAdaptorServer去展示对应的MBean信息。

关键代码

  1. beforeExecute
 protected void beforeExecute(Thread t, Runnable r) {
         // 记录每次执行的开始时间
        startTime.set(System.currentTimeMillis());
    }
  1. afterExecute
 protected void afterExecute(Runnable r, Throwable t) {
        long costTime = System.currentTimeMillis() - startTime.get(); // 计算任务花费时间
        startTime.remove(); // 清空开始时间
        maxCostTime = Math.max(maxCostTime, costTime);
        if (totalTasks.get() == 0) {
            minCostTime = costTime;
        }
        minCostTime = Math.min(minCostTime, costTime);
        totalCostTime.addAndGet(costTime);
        totalTasks.incrementAndGet();
        activeCount = this.getActiveCount();
}
  1. registerMBean
    public static void registerMBean(Object obj, ObjectName objectName) {
        try {
            // 注册MBean信息
            server.registerMBean(obj, objectName);
        } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
            e.printStackTrace();
        }
    }

效果图

线程池监控 - 简易版

项目地址:montos-threadPool-monitoring
欢迎小伙伴们star以及fork等。

上一篇:JAVA动态代理和CGLIB的区别


下一篇:Spring中的DeferredResult执行