How to Get the Number of Threads in a Java Process – 如何获取一个Java进程中的线程数

最后修改: 2021年 6月 26日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Thread is the basic unit of concurrency in Java. In most cases, the throughput of an application increases when multiple threads are created to do tasks in parallel.

线程是Java中并发的基本单位。在大多数情况下,当创建多个线程来并行完成任务时,应用程序的吞吐量会增加。

However, there’s always a saturation point. After all, the throughput of an application depends on CPU and memory resources. After a certain limit, increasing the number of threads can result in high memory, thread context switching, etc. 

然而,总是有一个饱和点。毕竟,一个应用程序的吞吐量取决于CPU和内存资源。在达到一定限度后,增加线程数量会导致高内存、线程上下文切换等问题。

So a good starting point in troubleshooting a high memory issue in a Java application is to monitor the number of threads. In this tutorial, we’ll look at some ways we can check the number of threads created by a Java process.

因此,在排除Java应用程序中的高内存问题时,一个很好的出发点是监控线程的数量。在本教程中,我们将看看有哪些方法可以检查一个Java进程所创建的线程数。

2. Graphical Java Monitoring Tools

2.图形化的Java监控工具

The simplest way to see the number of threads in Java is to use a graphical tool like Java VisualVM. Apart from the application threads, Java VisualVM also lists the GC or any other threads used by the application like JMX threads.

查看 Java 中线程数量的最简单方法是使用一个图形化工具,如 Java VisualVM除了应用程序的线程外,Java VisualVM还列出了GC或应用程序使用的任何其他线程,如JMX线程

Furthermore, it also shows stats like thread states along with their duration:

此外,它还显示了线程状态及其持续时间等统计信息。

Java VisualVM

Monitoring the number of threads is the most basic feature in Java VisualVM. Generally speaking, graphical tools are more advanced and allow live monitoring of an application. For example, Java VisualVM allows us to sample our CPU stack traces and thus find a class or a method that may cause CPU bottleneck.

监测线程数是Java VisualVM中最基本的功能。一般来说,图形化的工具更先进,可以对一个应用程序进行实时监控。例如,Java VisualVM允许我们对CPU堆栈痕迹进行采样,从而找到可能导致CPU瓶颈的类或方法。

Java VisualVM is distributed with the JDK installation on Windows machines.  For applications deployed on Linux, we need to connect to the application remotely. This requires JMX VM arguments.

Java VisualVM是与Windows机器上的JDK安装一起分发的。 对于部署在 Linux 上的应用程序,我们需要远程连接到该应用程序。这需要JMX VM参数。

Therefore, such tools won’t work if an application is already running without these parameters. In a later section, we’ll see how we can get the number of threads using command-line tools.

因此,如果一个应用程序已经在运行而没有这些参数,这样的工具就不会起作用。在后面一节中,我们将看到如何使用命令行工具获得线程数。

3. Java APIs

3.Java APIs

In some use cases, we may want to find the number of threads within the application itself. For example, to display on monitoring dashboards or exposing it in logs.

在一些用例中,我们可能想找到应用程序本身的线程数。例如,在监控仪表板上显示或在日志中暴露出来。

In such cases, we rely on Java APIs to get the thread count. Thankfully, there’s an activeCount() API in the Thread class:

在这种情况下,我们要依靠Java API来获取线程数。值得庆幸的是,在Thread 类中有一个activeCount() API。

public class FindNumberofThreads {
    public static void main(String[] args) {
        System.out.println("Number of threads " + Thread.activeCount());
    }
}

And the output will be:

而输出将是。

Number of threads 2

Notably, if we see the number of threads in Java VisualVM, we’ll see more threads for the same application. This is because activeCount() only returns the number of threads in the same ThreadGroupJava divides all the threads into groups for easier management.

值得注意的是,如果我们看到Java VisualVM中的线程数,我们会看到同一个应用程序的线程数更多。这是因为activeCount()只返回同一ThreadGroup中的线程数量。Java将所有的线程分为一组,以方便管理。

In this example, we have just the parent ThreadGroup, i.e., main:

在这个例子中,我们只有父组ThreadGroup,,即main:

public static void main(String[] args) {
    System.out.println("Current Thread Group - " + Thread.currentThread().getThreadGroup().getName());
}
Current Thread Group - main

If there are many thread groups in a Java application, activeCount() won’t give a correct output. For example, it won’t return the number of GC threads.

如果一个Java应用程序中有许多线程组,activeCount()将不会给出正确的输出。例如,它将不会返回GC线程的数量。

In such scenarios, we can use the JMX API:

在这种情况下,我们可以使用JMX API

public static void main(String[] args) {
    System.out.println("Total Number of threads " + ManagementFactory.getThreadMXBean().getThreadCount());
}

This API returns the total number of threads from all thread groups, GC, JMX, etc.:

该API返回所有线程组、GC、JMX等的线程总数。

Total Number of threads 6

As a matter of fact, the JMX graphical tools like Java VisualVM use the same API for their data.

事实上,像Java VisualVM这样的JMX图形化工具也使用相同的API来获取数据。

4. Command-Line Tools

4.命令行工具

Previously, we discussed Java VisualVM, a graphical tool for analyzing live threads in an application. Although it’s a great tool for live visualization of threads, it has a minor impact on application performance. And hence it’s not recommended for production environments.

之前,我们讨论了Java VisualVM,这是一个用于分析应用程序中实时线程的图形化工具。虽然它是一个用于实时可视化线程的伟大工具,但它对应用程序的性能影响不大。因此不建议在生产环境中使用它

Moreover, as we discussed, Java VisualVM requires remote connectivity in Linux. And in fact, in some cases, it requires additional configuration. For example, an application running inside a Docker or Kubernetes would require additional service and port configuration.

此外,正如我们所讨论的,Java VisualVM在Linux中需要远程连接。而事实上,在某些情况下,它需要额外的配置。例如,在Docker或Kubernetes内运行的应用程序将需要额外的服务和端口配置。

In such cases, we have to rely on command-line tools in the host environment to get the thread count.

在这种情况下,我们必须依靠主机环境中的命令行工具来获得线程数。

Luckily, Java provides few commands to take a thread dump. We can analyze a thread dump either as a text file or use a thread dump analyzer tool to check the number of threads along with their state.

幸运的是,Java提供了一些命令来获取线程转储。我们可以将线程转储作为一个文本文件来分析,或者使用线程转储分析工具来检查线程的数量和它们的状态。

Alibaba Arthas is another great command-line tool that doesn’t require remote connectivity or any special configuration.

Alibaba Arthas是另一个伟大的命令行工具,不需要远程连接或任何特殊配置。

Additionally, we can get information about threads from a few Linux commands as well. For example, we can use the top command to display all the threads of any Java application:

此外,我们也可以从一些Linux命令中获得有关线程的信息。例如,我们可以使用top命令来显示任何Java应用程序的所有线程

top -H -p 1

Here, -H is a command-line option to display every thread in a Java process. Without this flag, the top command will display combined stats for all threads in the process. The -p option filters the output by process id of the target application:

这里,-H是一个命令行选项,用于显示Java进程中的每个线程。如果没有这个标志,top命令将显示进程中所有线程的综合统计信息。-p选项按目标应用程序的进程ID过滤输出。

top - 15:59:44 up 7 days, 19:23,  0 users,  load average: 0.52, 0.41, 0.36
Threads:  37 total,   0 running,  37 sleeping,   0 stopped,   0 zombie
%Cpu(s):  3.2 us,  2.2 sy,  0.0 ni, 93.4 id,  0.8 wa,  0.0 hi,  0.3 si,  0.0 st
MiB Mem :   1989.2 total,    110.2 free,   1183.1 used,    695.8 buff/cache
MiB Swap:   1024.0 total,    993.0 free,     31.0 used.    838.8 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   1 flink     20   0 2612160 304084  29784 S   0.0  14.9   0:00.07 java
  275 flink     20   0 2612160 304084  29784 S   0.0  14.9   0:02.87 java
  276 flink     20   0 2612160 304084  29784 S   0.0  14.9   0:00.37 VM Thread
  277 flink     20   0 2612160 304084  29784 S   0.0  14.9   0:00.00 Reference Handl
  278 flink     20   0 2612160 304084  29784 S   0.0  14.9   0:00.00 Finalizer
  279 flink     20   0 2612160 304084  29784 S   0.0  14.9   0:00.00 Signal Dispatch

As seen above, it shows the thread id, i.e., PID and per-thread CPU and memory utilization. Similar to Java VisualVM, the top command will list all the threads, including GC, JMX, or any other sub-process.

如上所示,它显示了线程ID,即PID和每线程的CPU和内存利用率。与Java VisualVM类似,顶部命令将列出所有线程,包括GC、JMX或任何其他子进程。

To find the process ID we used as an argument in the above command, we can use the ps command:

为了找到我们在上述命令中作为参数使用的进程ID,我们可以使用ps命令。

ps -ef | grep java

As a matter of fact, we can use the ps command to list the threads as well:

事实上,我们也可以使用ps命令来列出线程:

ps -e -T | grep 1

The -T option tells the ps command to list all the threads started by the application:

-T选项告诉ps命令,列出应用程序启动的所有线程。

1     1 ?        00:00:00 java
1   275 ?        00:00:02 java
1   276 ?        00:00:00 VM Thread
1   277 ?        00:00:00 Reference Handl
1   278 ?        00:00:00 Finalizer
1   279 ?        00:00:00 Signal Dispatch
1   280 ?        00:00:03 C2 CompilerThre
1   281 ?        00:00:01 C1 CompilerThre

Here, the first column is the PID, and the second column shows the Linux thread ID for each thread.

这里,第一列是PID,第二列显示每个线程的Linux线程ID。

5. Conclusion

5.总结

In this article, we saw that there are various ways we can find the number of threads in a Java application. In most cases, using the command-line options like the top or ps command should be the go-to way.

在这篇文章中,我们看到有各种方法可以找到Java应用程序中的线程数。在大多数情况下,使用命令行选项,如topps命令,应该是首选的方法

However, in some situations, we may also need graphical tools like the Java VisualVM. All code samples are available over on GitHub.

然而,在某些情况下,我们可能还需要像Java VisualVM这样的图形化工具。所有的代码样本都可以在GitHub上找到over