评论

收藏

[Java] 教你如何监控 Java 线程池运行状态的操作(必看)

编程语言 编程语言 发布于:2021-09-11 23:03 | 阅读数:683 | 评论:0

这篇文章主要介绍了教你如何监控 Java 线程池运行状态的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
之前写过一篇 java 线程池的使用介绍文章《线程池全面解析》,全面介绍了什么是线程池、线程池核心类、线程池工作流程、线程池分类、拒绝策略、及如何提交与关闭线程池等。
但在实际开发过程中,在线程池使用过程中可能会遇到各方面的故障,如线程池阻塞,无法提交新任务等。
如果你想监控某一个线程池的执行状态,线程池执行类 threadpoolexecutor 也给出了相关的 api, 能实时获取线程池的当前活动线程数、正在排队中的线程数、已经执行完成的线程数、总线程数等。
总线程数 = 排队线程数 + 活动线程数 + 执行完成的线程数
下面给出一个线程池使用示例,及教你获取线程池状态
private static executorservice es = new threadpoolexecutor(50, 100, 0l, timeunit.milliseconds,
 new linkedblockingqueue<runnable>(100000));
public static void main(string[] args) throws exception {
 for (int i = 0; i < 100000; i++) {
 es.execute(() -> {
 system.out.print(1);
 try {
 thread.sleep(1000);
 } catch (interruptedexception e) {
 e.printstacktrace();
 }
 });
 }
 
 threadpoolexecutor tpe = ((threadpoolexecutor) es);
 while (true) {
 system.out.println();
 int queuesize = tpe.getqueue().size();
 system.out.println("当前排队线程数:" + queuesize);
 int activecount = tpe.getactivecount();
 system.out.println("当前活动线程数:" + activecount);
 long completedtaskcount = tpe.getcompletedtaskcount();
 system.out.println("执行完成线程数:" + completedtaskcount);
 long taskcount = tpe.gettaskcount();
 system.out.println("总线程数:" + taskcount);
 thread.sleep(3000);
 }
}
线程池提交了 100000 个任务,但同时只有 50 个线程在执行工作,我们每陋 3 秒来获取当前线程池的运行状态。
第一次程序输出:
当前排队线程数:99950
当前活动线程数:50
执行完成线程数:0
总线程数(排队线程数 + 活动线程数 + 执行完成线程数):100000
第二次程序输出:
当前排队线程数:99800
当前活动线程数:50
执行完成线程数:150
总线程数(排队线程数 + 活动线程数 + 执行完成线程数):100000
活动线程数和总线程数是不变的,排队中的线程数和执行完成的线程数不断在变化,
直到所有任务执行完毕,最后输出:
当前排队线程数:0
当前活动线程数:0
执行完成线程数:100000
总线程数(排队线程数 + 活动线程数 + 执行完成线程数):100000
这样,你了解了这些 api 的使用方法,你想监控线程池的状态就非常方便了。
补充:java线程及jvm监控工具
java线程状态
线程的五种状态
* 新建:new(时间很短)
* 运行:runnable
* 等待:waitting(无限期等待),timed waitting(限期等待)
* 阻塞:blocked
* 结束:terminated(时间很短)
DSC0000.jpg

jvm监控工具
一、jstack
介绍:
jstack用于打印出给定的java进程id或core file或远程调试服务的java堆栈信息。
如果是在64位机器上,需要指定选项"-j-d64",windows的jstack使用方式只支持以下的这种方式:jstack [-l] pid
如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。
另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。
使用:
1、查看运行程序的进程号
DSC0001.jpg

2、jstack dump当前线程状态
DSC0002.jpg

3、根据当前抓取到的信息进行进一步的分析
二、jvisualvm
jdk自带有个jvisualvm工具、该工具是用来监控java运行程序的cpu、内存、线程等的使用情况。并且使用图表的方式监控java程序、还具有远程监控能力。
前期准备
1、上传tomcat到虚拟机,webapps下存在prefteach包
2、监控之前先对jvm加监控参数,在tomcat的bin目录下,catalina.sh文件中,搜索java_opts=,在if里面,添加:
-dcom.sun.management.jmxremote.port=10086 -dcom.sun.management.jmxremote.ssl=false -dcom.sun.management.jmxremote.authenticate=false -djava.rmi.server.hostname=192.168.1.101
以上添加的内容,需要修改两处
1-改port
2-改hostname为本机ip
3、启动tomcat并打开输出日志:./startup.sh ../logs/catalina.out
jvisualvm使用
1、windows键+r键 输入jvisualvm回车
2、右键远程添加远程主机
DSC0003.jpg

3、在 主机ip 上右键添加jmv连接
DSC0004.jpg

4、输入远程连接的端口号点击确定
DSC0005.jpg

5、双击192.168.1.101:10086,打开如下图所示的界面
DSC0006.jpg

6、进入jvisualvm时时查看程序运行状态
DSC0007.jpg

注释:在测试环境中有可能没有权限在服务器上添加需要远程连接的配置,这样只能使用jstack
补充:java 如何获得线程池中正在执行的线程数
java中线程池的监控可以检测到正在执行的线程数。
通过线程池提供的参数进行监控。线程池里有一些属性在监控线程池的时候可以使用
taskcount:线程池需要执行的任务数量。
completedtaskcount:线程池在运行过程中已完成的任务数量。小于或等于taskcount。
largestpoolsize:线程池曾经创建过的最大线程数量。通过这个数据可以知道线程池是否满过。如等于线程池的最大大小,则表示线程池曾经满了。
getpoolsize:线程池的线程数量。如果线程池不销毁的话,池里的线程不会自动销毁,所以这个大小只增不+ getactivecount:获取活动的线程数。
通过扩展线程池进行监控。通过继承线程池并重写线程池的beforeexecute,afterexecute和terminated方法,我们可以在任务执行前,执行后和线程池关闭前干一些事情。
如监控任务的平均执行时间,最大执行时间和最小执行时间等。这几个方法在线程池里是空方法。
如:
protected void beforeexecute(thread t, runnable r) { }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持CodeAE代码之家。如有错误或未考虑完全的地方,望不吝赐教。
原文链接:https://blog.csdn.net/youanyyou/article/details/80405873

关注下面的标签,发现更多相似文章