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

作者:Java技术栈 时间:2023-02-09 04:34:13 

之前写过一篇 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(时间很短)

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

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、查看运行程序的进程号

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

2、jstack dump当前线程状态

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

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、右键远程添加远程主机

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

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

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

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

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

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

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

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

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

注释:在测试环境中有可能没有权限在服务器上添加需要远程连接的配置,这样只能使用jstack

补充:java 如何获得线程池中正在执行的线程数

java中线程池的监控可以检测到正在执行的线程数。

通过线程池提供的参数进行监控。线程池里有一些属性在监控线程池的时候可以使用

taskCount:线程池需要执行的任务数量。

completedTaskCount:线程池在运行过程中已完成的任务数量。小于或等于taskCount。

largestPoolSize:线程池曾经创建过的最大线程数量。通过这个数据可以知道线程池是否满过。如等于线程池的最大大小,则表示线程池曾经满了。

getPoolSize:线程池的线程数量。如果线程池不销毁的话,池里的线程不会自动销毁,所以这个大小只增不+ getActiveCount:获取活动的线程数。

通过扩展线程池进行监控。通过继承线程池并重写线程池的beforeExecute,afterExecute和terminated方法,我们可以在任务执行前,执行后和线程池关闭前干一些事情。

如监控任务的平均执行时间,最大执行时间和最小执行时间等。这几个方法在线程池里是空方法。

如:


protected void beforeExecute(Thread t, Runnable r) { }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

来源:https://blog.csdn.net/youanyyou/article/details/80405873

标签:Java,线程池,状态
0
投稿

猜你喜欢

  • 新手小白看过来学JAVA必过IO流File字节流字符流

    2022-09-22 07:42:02
  • Java contains用法示例

    2023-01-12 19:48:34
  • C# WinForm开发中使用XML配置文件实例

    2022-09-07 23:04:03
  • Android仿微信QQ设置图形头像裁剪功能

    2022-06-21 10:12:25
  • 基于SpringBoot生成二维码的几种实现方式

    2022-02-27 16:24:31
  • C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?

    2022-06-25 12:34:55
  • 详解如何在Java中加密和解密zip文件

    2022-12-07 12:26:46
  • Java容器HashMap与HashTable详解

    2022-03-05 19:25:00
  • Spring的refresh()方法相关异常解析

    2021-12-08 07:39:07
  • C#实现获取不同对象中名称相同属性的方法

    2021-11-04 19:26:32
  • C#查找对象在ArrayList中出现位置的方法

    2022-08-06 19:19:35
  • 将来会是Python、Java、Golang三足鼎立的局面吗

    2023-11-22 09:18:31
  • Java递归算法遍历部门代码示例

    2021-08-03 20:59:20
  • Java事务管理学习之Hibernate详解

    2023-06-07 03:14:09
  • 解析在内部循环中Continue外部循环的使用详解

    2023-09-24 08:03:50
  • Android开发环境安装和配置图文教程

    2023-08-04 16:58:26
  • Android基于Fresco实现圆角和圆形图片

    2023-02-14 20:03:29
  • Android布局中gravity与layout_gravity属性说明

    2021-08-27 10:51:31
  • java实现推箱子小游戏

    2023-02-09 04:57:52
  • java如何让带T的时间格式化

    2022-12-22 10:44:28
  • asp之家 软件编程 m.aspxhome.com