首页 > 其他分享 >线程池监控1-监控任务执行时间

线程池监控1-监控任务执行时间

时间:2024-09-24 21:02:55浏览次数:1  
标签:maximumPoolSize poolName int keepAliveTime monitorLevel 任务 线程 监控 workQueue

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

参考:https://cloud.tencent.com/developer/article/1491221

标签:maximumPoolSize,poolName,int,keepAliveTime,monitorLevel,任务,线程,监控,workQueue
From: https://www.cnblogs.com/xkzhangsanx/p/18430001

相关文章

  • 任务3:PDF转换器的应用
    使用PDF转换器添加水印的步骤如下:选择PDF转换器:选择一个支持添加水印功能的PDF转换器,如LightPDF打开PDF文件:启动转换器,点击“打开PDF文件”选项,选择需要添加水印的PDF文件设置水印参数:在顶部菜单栏中,依次选择“文档”-“水印”-“添加”。水印类型分为文本和图片两种,根据需......
  • 任务1:去除水印(理论部分)
    水印是一种用于保护版权的技术,通过在图像、视频或文档上添加不显眼的标记来表明所有权。水印的功能包括明确标示内容的所有权,防止未经授权的复制和分发,同时帮助识别原始所有者,通过水印信息还能追溯非法传播的来源。而去除水印可能涉及以下法律风险,可能导致法律诉讼、罚款或其他法......
  • 任务2:使用Canva的绘图工具
    该海报供小学自然课堂使用,围绕“土壤”这一主题,通过图像、文字和绘画活动来形象阐述土壤的功能。设计思路如下:1.【视觉元素】●土壤层次:展示土壤的不同层次,如表土、底土等,可以用图解的方式表示。●生物多样性:画出土壤中的微生物、昆虫、植物根系等,展示土壤生态系统的多样性。......
  • JavaEE——多线程
    接着上篇博客我们已经学习了进程的相关概念,了解到进程里面的相关重要属性,那么这篇博客呢我们要学习一个新的知识点——线程!一、引入进程的目的首先引入进程这个概念,是为了解决“并发编程”这样的问题。因为CPU再往小了做,比较困难了,这是因为CPU进入了多核心的时代,要想进一......
  • ELK-03-skywalking监控linux系统
    文章目录前言一、下载node_exporter二、启动node_exporter三、下载OpenTelemetryCollector四、启动OpenTelemetryCollector4.1将配置文件下载到同级目录4.2启动五、查看总结前言skywalking安装完成后,开始我们的第一个监控-监控linux系统。参考官方文档:https:......
  • JavaEE——多线程Thread 类及常见方法
    目录 一、Thread(Stringname)二、是否后台线程isDeamon()三、是否存活isAlive()四、run()方法和start()方法的区别五、中断线程法一:法二:六、线程等待join()七、线程休眠sleep()一、Thread(Stringname)定义:这个东西是给线程(thread对象)起一个名字。起一个......
  • EasyCVR视频监控平台调取接口提示“认证过期”是什么原因?
    有用户反馈,调取分组绑定通道接口提示认证过期,添加token还是出现此问题,于是请求我们协助排查。拿到现场后,技术人员进行接口复现。使用接口工具调取/api/v1/label/updatechannels复现问题,添加token之后无法鉴权到验证。随后调取其它接口发现正常,于是再次对其在平台的操作对比,发现此接......
  • @Scheduled注解停止定时任务、@Scheduled设置定时任务不启用、springboot 配置Schedul
    文章目录一、关闭定时任务1.1、方法一:注释@EnableScheduling注解1.1.1、原理1.2、方法二:不加载ScheduledAnnotationBeanPostProcessor类1.3、方法三:注释@Scheduled注解1.4、方法四:设置@Scheduled注解cron时间不开启(推荐)1.4.1、原理在项目中我们可能会遇到这样一......
  • 基于Node.js+vue智能宠物监控系统(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着城市化进程的加速和人们生活质量的提升,宠物已成为许多家庭的重要成员。然而,现代生活节奏的加快使得许多宠物主人在日常照顾宠物时面临时间上的挑战。传......
  • Java多线程
    文章目录前言1实现多线程1.1多线程概述1.2多线程的实现方式1.3线程休眠1.4线程优先级1.5守护线程2线程同步2.1同步代码块2.2Lock锁2.3死锁3生产者消费者3.1生产者和消费者模式概述3.2阻塞队列基本使用3.3阻塞队列实现等待唤醒机制前言"劝君莫惜金......