zoukankan      html  css  js  c++  java
  • java线程池监控

    原因

    最近在完善公司的基础发布平台的时候,使用到了一线程去做一些异步的事情,在开发环境和测试环境验证没有任何问题,但是在程序在生产运行一段时间后,发现没有得到自己想要的结果,为此开始了漫长的排查bug的之路,因为用到了一些线程,但是实际又没有对这些线程足够的监控,所以在排查问题的时候也是历经艰难险阻;

    原始代码

    
    

    protected ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);


    /**
    * 同步应用的jenkins状态
    */
    public void threadASyncAppJenkinsStatus() {
    executorService.scheduleAtFixedRate(() -> {
    List<ArchitectureApp> architectureApps = architectureAppMapper.listArchitectureApp();
    architectureApps.parallelStream().forEach(architectureApp -> syncJenkinsBuild(architectureApp.getName(), ArchitectureType.APP));

    }, 0, 6, TimeUnit.SECONDS);

    }

    /**
    * 同步组件的jenkins状态
    */
    public void syncComponentJenkinsStatus() {
    executorService.scheduleAtFixedRate(() -> {
    List<ArchitectureComponent> architectureComponents = architectureComponentMapper.listArchitectureComponent();
    architectureComponents.parallelStream().forEach(architectureComponent -> syncJenkinsBuild(architectureComponent.getName(), ArchitectureType.COMPONENT));
    }, 0, 6, TimeUnit.SECONDS);

    }
     

    这是其中一部分的代码,做的事情很简单,程序每隔6s就去轮询组件和应用的状态,然后后面我会通过websocket同步到前端页面。这是一段很简单的代码,很难想象这段代码可能出错。但是事与愿违,通过开发和测试环境的测试,在上到生产运行了两天发现前端页面的jenkins状态并没有同步。而通过查看日志,也没法观察问题出在哪,所以只能另寻他法;

    ExecutorsMonitor线程监控类

    以下是我们开发的一个线程池工具类,该工具类扩展ScheduledThreadPoolExecutor实现了线程池监控功能,能实时将线程池使用信息打印到日志中,方便我们进行问题排查、系统调优。具体代码如下

    @Slf4j
    class ExecutorsMonitor extends ScheduledThreadPoolExecutor {
    
    
        private ConcurrentHashMap<String, Date> startTimes;
        private String poolName;
    
        /**
         * 调用父类的构造方法,并初始化HashMap和线程池名称
         *
         * @param corePoolSize 线程池核心线程数
         * @param poolName     线程池名称
         */
        public ExecutorsMonitor(int corePoolSize, String poolName) {
            super(corePoolSize);
            this.startTimes = new ConcurrentHashMap<>();
            this.poolName = poolName;
        }
    
        /**
         * 线程池延迟关闭时(等待线程池里的任务都执行完毕),统计线程池情况
         */
        @Override
        public void shutdown() {
            super.shutdown();
        }
    
        /**
         * 线程池立即关闭时,统计线程池情况
         */
        @Override
        public List<Runnable> shutdownNow() {
            return super.shutdownNow();
        }
    
        /**
         * 任务执行之前,记录任务开始时间
         */
        @Override
        protected void beforeExecute(Thread t, Runnable r) {
            startTimes.put(String.valueOf(r.hashCode()), new Date());
        }
    
        /**
         * 任务执行之后,计算任务结束时间
         */
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            Date startDate = startTimes.remove(String.valueOf(r.hashCode()));
            Date finishDate = new Date();
            long diff = finishDate.getTime() - startDate.getTime();
            // 统计任务耗时、初始线程数、核心线程数、正在执行的任务数量、已完成任务数量、任务总数、队列里缓存的任务数量、池中存在的最大线程数、最大允许的线程数、线程空闲时间、线程池是否关闭、线程池是否终止
            log.info(String.format(this.poolName
                            + "-pool-monitor: Duration: %d ms, PoolSize: %d, CorePoolSize: %d, Active: %d, Completed: %d, Task: %d, Queue: %d, LargestPoolSize: %d, MaximumPoolSize: %d,  KeepAliveTime: %d, isShutdown: %s, isTerminated: %s",
                    diff, this.getPoolSize(), this.getCorePoolSize(), this.getActiveCount(), this.getCompletedTaskCount(), this.getTaskCount(),
                    this.getQueue().size(), this.getLargestPoolSize(), this.getMaximumPoolSize(), this.getKeepAliveTime(TimeUnit.MILLISECONDS),
                    this.isShutdown(), this.isTerminated()));
        }
    
        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, String poolName) {
            return new ExecutorsMonitor(corePoolSize, poolName);
        }
    
    }
    

      

    后来在生产终于定位问题,发现线程内部后来停止,同时发现的还有报错,通过查阅资料发现,原来线程发生异常后会退出,通过try catch很好的解决了这个问题

  • 相关阅读:
    c++检测本机网络
    ShellExecuteEx 阻塞和异步调用进程的两种方法
    QImage 转base64
    C 位域运算
    Linq 取差集 交集等
    Linq 筛选出一条数据
    Linq查询出结果集中重复数据
    使AspNetPager控件中文显示分页信息
    C盘瘦身,可以让你的电脑C盘恢复到刚安装时的大小
    Linq Distinct List 去重复
  • 原文地址:https://www.cnblogs.com/clovejava/p/10053916.html
Copyright © 2011-2022 走看看