原因

最近在完善公司的基础发布平台的时候,使用到了一线程去做一些异步的事情,在开发环境和测试环境验证没有任何问题,但是在程序在生产运行一段时间后,发现没有得到自己想要的结果,为此开始了漫长的排查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很好的解决了这个问题

java线程池监控的更多相关文章

  1. 干货 | 教你如何监控 Java 线程池运行状态

    之前写过一篇 Java 线程池的使用介绍文章<线程池全面解析>,全面介绍了什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中, ...

  2. 干货:教你如何监控 Java 线程池运行状态

    之前写过一篇 Java 线程池的使用介绍文章<线程池全面解析>,全面介绍了什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中, ...

  3. Java并发(六)线程池监控

    目录 一.线程池监控参数 二.线程池监控类 三.注意事项 在上一篇博文中,我们介绍了线程池的基本原理和使用方法.了解了基本概念之后,我们可以使用 Executors 类创建线程池来执行大量的任务,使用 ...

  4. java线程池

    http://cuisuqiang.iteye.com/blog/2019372 Java四种线程池的使用 java线程线程池监控 Java通过Executors提供四种线程池,分别为:newCach ...

  5. (转载)JAVA线程池管理

    平时的开发中线程是个少不了的东西,比如tomcat里的servlet就是线程,没有线程我们如何提供多用户访问呢?不过很多刚开始接触线程的开发攻城师却在这个上面吃了不少苦头.怎么做一套简便的线程开发模式 ...

  6. 基于 JVMTI 实现 Java 线程的监控(转)

    随着多核 CPU 的日益普及,越来越多的 Java 应用程序使用多线程并行计算来充分发挥整个系统的性能.多线程的使用也给应用程序开发人员带来了巨大的挑战,不正确地使用多线程可能造成线程死锁或资源竞争, ...

  7. 这么说吧,java线程池的实现原理其实很简单

    好处 : 线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配.调优和监控,有以下好处: 1.降低资源消耗: 2.提高响应速度: 3.提高线 ...

  8. 【java线程系列】java线程系列之java线程池详解

    一线程池的概念及为何需要线程池: 我们知道当我们自己创建一个线程时如果该线程执行完任务后就进入死亡状态,这样如果我们需要在次使用一个线程时得重新创建一个线程,但是线程的创建是要付出一定的代价的,如果在 ...

  9. Java 线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

随机推荐

  1. Asp.Net Core 第05局:读取配置

    前言 本文介绍Asp.Net Core 读取配置文件. 环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 开局 前期准备             1.添加app.j ...

  2. python 装饰器 对类和函数的装饰

    #装饰器:对类或者函数进行功能的扩展  很多需要缩进的没有进行缩进'''#第一步:基本函数def laxi(): print('拉屎')#调用函数laxi()laxi() print('======= ...

  3. ubuntu 使用pecl 安装 PHP AMQP Extension

    下载扩展: sudo apt-get -y install gcc make autoconf libc-dev pkg-config sudo apt-get -y install libssl-d ...

  4. 实验报告(五)&第七周学习总结

    实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法. 实验要求 掌握使用抽象类的方法. 掌握使用系统接口的技术和创建自定义接口的方法. 了解 Java 系统包的结构. 掌握创建自定义包 ...

  5. 使用自编译的Emacs26.0.50build10版本,helm报错(已解决)

    使用自编译的Emacs26.0.50build10版本,helm报错(已解决) */--> code {color: #FF0000} pre.src {background-color: #0 ...

  6. 小程序中this.setData的使用和注意事项

    前言:微信小程序中经常需要用到this.setData({})把变量值渲染到视图层,那到底什么是this.setData,如何使用?需要注意哪些?作为一个初学者,分享一点我的经验,希望大家批评指正. ...

  7. 第八组Postmortem事后分析

    第八组Postmortem事后分析 一.团队成员总结的改进和教训 隆晋威:Beta阶段完善架构设计,分工更加明确,文档更丰富,交流带来开销减少.Alpha技术选型不固定,分工混乱,没有方便的测试引擎, ...

  8. 简易的富文本编辑器WangEditor

    网址http://www.wangeditor.com/ var E = window.wangEditor; var editor = new E('#editor') // 或者 var edit ...

  9. Centos7 忘记密码的情况下,修改root密码

    linux管理员忘记root密码,需要进行找回操作. 本文基于centos7环境进行操作,由于centos的版本是有差异的,继续之前请确定好版本 一.重启系统,在开机过程中,快速按下键盘上的方向键↑和 ...

  10. Struts2关于命名空间的例子

    佐证了这样一个原则,package存在,但action没找到,就自动去默认空间去找.如果package不存在,则自动向上一级目录找,一级级倒到根目录.  根目录再没找到,再去默认目录找 网上对于命名空 ...