Java
线程池想必大家都不会陌生,对于一些可以并发可以执行的任务,我们优先选择考虑线程池进行操作,但是对于其中一些指标出问题,我们很难去排查,这里就带大家撸一个简易版本的线程池监控。
ThreadPoolExecutor
在原生的线程池中,许多我们想监控的变量都是private
的(满满的恶意),但是有些是提供了get
方法帮助我们去获取(除了运行状态字段)。
我们要想完成达到监控的效果,就要对此进行扩展,不满足于只有get
方法的字段监控。这个时候就需要介绍下原生线程池中的两个方法:
-
beforeExecute(Thread t, Runnable r)
该方法是执行任务之前执行。 -
afterExecute(Runnable r, Throwable t)
该方法是执行任务之后执行(必执行,放置在finally
语句中)。
我们可以在这两个方法中增加额外操作,帮助我们可以监控其他指标。
MBean
MBean
就是一种规范的JavaBean,通过集成和实现一套标准的Bean接口,这种叫MBean,Mbean注册到MBeanServer中。(可以理解为一种JVM
允许状态辅助查询的Bean
)。
在本Demo
中,我是通过MBean
的形式去进行指标的监控,所以也帮大家去了解下它。
在此,我使用的HtmlAdaptorServer
去展示对应的MBean
信息。
关键代码
beforeExecute
protected void beforeExecute(Thread t, Runnable r) {
// 记录每次执行的开始时间
startTime.set(System.currentTimeMillis());
}
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();
}
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
等。