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很好的解决了这个问题
java线程池监控的更多相关文章
- 干货 | 教你如何监控 Java 线程池运行状态
之前写过一篇 Java 线程池的使用介绍文章<线程池全面解析>,全面介绍了什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中, ...
- 干货:教你如何监控 Java 线程池运行状态
之前写过一篇 Java 线程池的使用介绍文章<线程池全面解析>,全面介绍了什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中, ...
- Java并发(六)线程池监控
目录 一.线程池监控参数 二.线程池监控类 三.注意事项 在上一篇博文中,我们介绍了线程池的基本原理和使用方法.了解了基本概念之后,我们可以使用 Executors 类创建线程池来执行大量的任务,使用 ...
- java线程池
http://cuisuqiang.iteye.com/blog/2019372 Java四种线程池的使用 java线程线程池监控 Java通过Executors提供四种线程池,分别为:newCach ...
- (转载)JAVA线程池管理
平时的开发中线程是个少不了的东西,比如tomcat里的servlet就是线程,没有线程我们如何提供多用户访问呢?不过很多刚开始接触线程的开发攻城师却在这个上面吃了不少苦头.怎么做一套简便的线程开发模式 ...
- 基于 JVMTI 实现 Java 线程的监控(转)
随着多核 CPU 的日益普及,越来越多的 Java 应用程序使用多线程并行计算来充分发挥整个系统的性能.多线程的使用也给应用程序开发人员带来了巨大的挑战,不正确地使用多线程可能造成线程死锁或资源竞争, ...
- 这么说吧,java线程池的实现原理其实很简单
好处 : 线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配.调优和监控,有以下好处: 1.降低资源消耗: 2.提高响应速度: 3.提高线 ...
- 【java线程系列】java线程系列之java线程池详解
一线程池的概念及为何需要线程池: 我们知道当我们自己创建一个线程时如果该线程执行完任务后就进入死亡状态,这样如果我们需要在次使用一个线程时得重新创建一个线程,但是线程的创建是要付出一定的代价的,如果在 ...
- Java 线程池(ThreadPoolExecutor)原理分析与使用
在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...
随机推荐
- TSV 与 CSV
TSV : Tab-separated values 用制表符分隔值. CSV : Comma-separated values 用逗号分隔值. 参考 RFC 4180 - Common Format ...
- php优化及高效提速问题小结
一. 在函数中,传递数组时使用 return 比使用 global 要高效,比如: function userloginfo($usertemp){ $detail=explode("&qu ...
- Linux下的tar压缩解压命令
tar 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个. -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件 下 ...
- ORCAL 数据库的约束以及SQL语言的四种类型
oracle数据库约束: 定义:要输入的这个值是一个什么样的值, 或者是哪个范围内的值 作用: 确保完整性, 确保精确性 1, 非空约束(not null) 记录一条信息的时候如果用户名和密码没有被记 ...
- 蛋糕仙人的javascript笔记
蛋糕仙人的javascript笔记:https://www.w3cschool.cn/kesyi/kesyi-nqej24rv.html
- go 学习之字符串
字符串 字符串是不可变值类型,内部⽤用指针指向 UTF-8 字节数组.默认值是空字符串 "".用索引号访问某字节,如 s[i], i不能是负数.不能⽤用序号获取字节元素指针,&am ...
- HDU 3622 Bomb Game(2-sat)
Bomb Game Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- rabbitmq-5-案例1-简单的案例
最简单的案例: https://gitee.com/n_zhe/rabbitmq-demo 通过简单的例子分析mq是怎样发送和拉取消息的: quickStart中的简单案例 通过简单的案例来 ...
- centos7.3安装wordpress
一.安装并配置数据库 1.安装mariadb #yum install -y mariadb-server mariadb 2.启动数据库并设置开机自启#systemctl start mariadb ...
- java web中的get和post(笔记)
W3CSchool 在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST. GET - 从指定的资源请求数据. POST - 向指定的资源提交要被处理的数据 GET 方法 ...