教你如何监控 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(时间很短)

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

2、jstack dump当前线程状态

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

如:

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

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

(0)

相关推荐

  • java并发包中CountDownLatch和线程池的使用详解

    1.CountDownLatch 现在做的这个华为云TaurusDB比赛中,参考的之前参加过阿里的PolarDB大赛的两个大佬的代码,发现都有用到CountDownLatch这个类,之前看代码的时候也看过,但是没有搞得很明白,自己写也写不出来,在此自己先学习一下. 字面理解:CountDownLatch:数量减少的门栓. 创建这样一个门栓 CountDownLatch countDownLatch = new CountDownLatch(count); 参数:count,门栓的计数次数. 在所

  • java 线程池keepAliveTime的含义说明

    之前对线程池中属性:keepAliveTime比较模糊,而且看过之后过一段时间就会忘掉,于是就在此记录一下. keepAliveTime的jdk中的解释为: 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间. 说的让人感觉比较模糊,总结一下大概意思为:比如说线程池中最大的线程数为50,而其中只有40个线程任务在跑,相当于有10个空闲线程,这10个空闲线程不能让他一直在开着,因为线程的存在也会特别好资源的,所有就需要设置一个这个空闲线程的存活时间,这么解释应该就很清楚了. 这样以后

  • java多线程CountDownLatch与线程池ThreadPoolExecutor/ExecutorService案例

    1.CountDownLatch: 一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行. 2.ThreadPoolExecutor/ExecutorService: 线程池,使用线程池可以复用线程,降低频繁创建线程造成的性能消耗,同时对线程的创建.启动.停止.销毁等操作更简便. 3.使用场景举例: 年末公司组织团建,要求每一位员工周六上午8点到公司门口集合,统一乘坐公司所租大巴前往目的地. 在这个案例中,公司作为主线程,员工作为子线程. 4.代码示例: package

  • java高级应用:线程池的全面讲解(干货)

    什么是线程池? 很简单,简单看名字就知道是装有线程的池子,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程的复用. 线程池的好处 我们知道不用线程池的话,每个线程都要通过new Thread(xxRunnable).start()的方式来创建并运行一个线程,线程少的话这不会是问题,而真实环境可能会开启多个线程让系统和程序达到最佳效率,当线程数达到一定数量就会耗尽系统的CPU和内存资源,也会造成GC频繁收集和停顿,因为每次创建和销毁一个线程都是要

  • Java 线程状态和等待唤醒机制和线程池的实现

    1.概念 线程一共有6中状态,相互之间可以互相转换. 等待唤醒案例(线程之间的通信) 实现: 等待唤醒案例:线程之间的通信 创建一个顾客线程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待) 创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子 注意: 顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行 同步使用的锁对象必须保证唯一 只有锁对象才能调用wait和noti

  • Java线程池运行状态监控实现解析

    在实际开发过程中,在线程池使用过程中可能会遇到各方面的故障,如线程池阻塞,无法提交新任务等. 如果你想监控某一个线程池的执行状态,线程池执行类 ThreadPoolExecutor 也给出了相关的 API, 能实时获取线程池的当前活动线程数.正在排队中的线程数.已经执行完成的线程数.总线程数等. 总线程数 = 排队线程数 + 活动线程数 + 执行完成的线程数. 线程池使用示例: private static ExecutorService es = new ThreadPoolExecutor(

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

    之前写过一篇 Java 线程池的使用介绍文章<线程池全面解析>,全面介绍了什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中,在线程池使用过程中可能会遇到各方面的故障,如线程池阻塞,无法提交新任务等. 如果你想监控某一个线程池的执行状态,线程池执行类 ThreadPoolExecutor 也给出了相关的 API, 能实时获取线程池的当前活动线程数.正在排队中的线程数.已经执行完成的线程数.总线程数等. 总线程数 = 排队线程数 +

  • 深入理解Java线程池从设计思想到源码解读

    线程池:从设计思想到源码解析 前言初识线程池线程池优势线程池设计思路 深入线程池构造方法任务队列拒绝策略线程池状态初始化&容量调整&关闭 使用线程池ThreadPoolExecutorExecutors封装线程池 解读线程池execute()addWorker()Worker类runWorker()processWorkerExit() 前言 各位小伙伴儿,春节已经结束了,在此献上一篇肝了一个春节假期的迟来的拜年之作,希望读者朋友们都能有收获. 根据穆氏哲学,投入越多,收获越大.我作此文时

  • 深度源码解析Java 线程池的实现原理

    java 系统的运行归根到底是程序的运行,程序的运行归根到底是代码的执行,代码的执行归根到底是虚拟机的执行,虚拟机的执行其实就是操作系统的线程在执行,并且会占用一定的系统资源,如CPU.内存.磁盘.网络等等.所以,如何高效的使用这些资源就是程序员在平时写代码时候的一个努力的方向.本文要说的线程池就是一种对 CPU 利用的优化手段. 线程池,百度百科是这么解释的: 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的

  • 超详细讲解Java线程池

    目录 池化技术 池化思想介绍 池化技术的应用 如何设计一个线程池 Java线程池解析 ThreadPoolExecutor使用介绍 内置线程池使用 ThreadPoolExecutor解析 整体设计 线程池生命周期 任务管理解析 woker对象 Java线程池实践建议 不建议使用Exectuors 线程池大小设置 线程池监控 带着问题阅读 1.什么是池化,池化能带来什么好处 2.如何设计一个资源池 3.Java的线程池如何使用,Java提供了哪些内置线程池 4.线程池使用有哪些注意事项 池化技术

  • java线程池ThreadPoolExecutor类使用详解

    在<阿里巴巴java开发手册>中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量:另一方面线程的细节管理交给线程池处理,优化了资源的开销.而线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式,这一方面是由于jdk中Executor框架虽然提供了如newFixedThreadPool().newSingleThreadExecutor().newCachedThreadPool(

  • java线程池ThreadPoolExecutor类使用小结

    目录 一.workQueue任务队列 二.拒绝策略 三.ThreadFactory自定义线程创建 四.ThreadPoolExecutor扩展 五.线程池线程数量 在<阿里巴巴java开发手册>中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量:另一方面线程的细节管理交给线程池处理,优化了资源的开销.而线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式,这一方面是由于jdk中E

  • Java线程池Executor用法详解

    目录 线程池类图 线程池的好处 new Thread的弊端 线程池核心类-ThreadPoolExecutor 使用Executors创建线程池 Executors.newCachedThreadPool Executors.newSingleThreadExecutor Executors.newFixedThreadPool Executors.newScheduledThreadPool 总结 如何定义线程池参数 线程池类图 我们最常使用的Executors实现创建线程池使用线程主要是用上

  • Java线程池框架核心代码解析

    前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和资源消耗都是很高的.线程池应运而生,成为我们管理线程的利器.Java 通过Executor接口,提供了一种标准的方法将任务的提交过程和执行过程解耦开来,并用Runnable表示任务. 下面,我们来分析一下 Java 线程池框架的实现ThreadPoolExecutor. 下面的分析基于JDK1.7 生命周期 ThreadPoolExecutor中,使用CAPACITY的高3位来表示运行状态,分别是:  1.RUNNING:接收

  • JAVA线程池原理实例详解

    本文实例讲述了JAVA线程池原理.分享给大家供大家参考,具体如下: 线程池的优点 1.线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用. 2.可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃. 线程池的创建 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQu

随机推荐