Javaプロセスのスレッド数を取得する方法
1. 概要
スレッドは、Javaの同時実行性の基本単位です。 ほとんどの場合、タスクを並行して実行するために複数のスレッドが作成されると、アプリケーションのスループットが向上します。
ただし、常に飽和点があります。 結局のところ、アプリケーションのスループットはCPUとメモリリソースに依存します。
したがって、Javaアプリケーションの高メモリの問題をトラブルシューティングするための良い出発点は、スレッドの数を監視することです。 このチュートリアルでは、Javaプロセスによって作成されたスレッドの数を確認するいくつかの方法を見ていきます。
2. グラフィカルJava監視ツール
Javaのスレッド数を確認する最も簡単な方法は、 JavaVisualVMなどのグラフィカルツールを使用することです。 アプリケーションスレッドとは別に、Java VisualVMは、GCまたはJMXスレッドなどのアプリケーションで使用されるその他のスレッドも一覧表示します。
さらに、スレッドの状態などの統計情報とその期間も表示されます。
スレッド数の監視は、JavaVisualVMの最も基本的な機能です。 一般的に、グラフィカルツールはより高度であり、アプリケーションのライブモニタリングを可能にします。 たとえば、Java VisualVMを使用すると、CPUスタックトレースをサンプリングして、CPUのボトルネックを引き起こす可能性のあるクラスまたはメソッドを見つけることができます。
Java VisualVMは、WindowsマシンへのJDKインストールとともに配布されます。
したがって、これらのパラメータなしでアプリケーションがすでに実行されている場合、このようなツールは機能しません。 後のセクションでは、コマンドラインツールを使用してスレッド数を取得する方法を説明します。
3. Java API
場合によっては、アプリケーション自体のスレッド数を調べたいことがあります。 たとえば、監視ダッシュボードに表示したり、ログに公開したりします。
このような場合、スレッド数を取得するためにJavaAPIに依存します。 ありがたいことに、スレッドクラスには activeCount()APIがあります。
public class FindNumberofThreads {
public static void main(String[] args) {
System.out.println("Number of threads " + Thread.activeCount());
}
}
そして、出力は次のようになります。
Number of threads 2
特に、Java VisualVMのスレッド数を確認すると、同じアプリケーションのスレッド数が増えます。 これは、activeCount()が同じスレッドの数のみを返すためです。
この例では、親 ThreadGroup、、つまり main:のみがあります。
public static void main(String[] args) {
System.out.println("Current Thread Group - " + Thread.currentThread().getThreadGroup().getName());
}
Current Thread Group - main
Javaアプリケーションに多数のスレッドグループがある場合、 activeCount()は正しい出力を提供しません。 たとえば、GCスレッドの数は返されません。
このようなシナリオでは、JMXAPIを使用できます。
public static void main(String[] args) {
System.out.println("Total Number of threads " + ManagementFactory.getThreadMXBean().getThreadCount());
}
このAPIは、すべてのスレッドグループ、GC、JMXなどからスレッドの総数を返します。
Total Number of threads 6
実際のところ、Java VisualVMなどのJMXグラフィカルツールは、データに同じAPIを使用します。
4. コマンドラインツール
以前、アプリケーションのライブスレッドを分析するためのグラフィカルツールであるJavaVisualVMについて説明しました。 スレッドをライブで視覚化するための優れたツールですが、アプリケーションのパフォーマンスにはわずかな影響しかありません。 したがって、本番環境にはお勧めしません。
さらに、前述したように、JavaVisualVMにはLinuxでのリモート接続が必要です。 実際、場合によっては、追加の構成が必要になります。 たとえば、DockerまたはKubernetes内で実行されているアプリケーションには、追加のサービスとポートの構成が必要になります。
このような場合、スレッド数を取得するには、ホスト環境のコマンドラインツールに依存する必要があります。
幸いなことに、Javaはスレッドダンプを取得するためのいくつかのコマンドを提供します。 スレッドダンプをテキストファイルとして分析するか、スレッドダンプアナライザツールを使用してスレッドの数とその状態を確認できます。
Alibaba Arthas は、リモート接続や特別な構成を必要としないもう1つの優れたコマンドラインツールです。
さらに、いくつかのLinuxコマンドからスレッドに関する情報を取得することもできます。 たとえば、topコマンドを使用して、任意のJavaアプリケーションのすべてのスレッドを表示できます:
top -H -p 1
ここで、 -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
上記のように、スレッドID、つまりPIDとスレッドごとのCPUおよびメモリ使用率が表示されます。 Java VisualVMと同様に、topコマンドは、GC、JMX、またはその他のサブプロセスを含むすべてのスレッドを一覧表示します。
上記のコマンドで引数として使用したプロセスIDを見つけるには、psコマンドを使用できます。
ps -ef | grep java
実際のところ、 ps コマンドを使用して、スレッドを一覧表示することもできます。
ps -e -T | grep 1
-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
ここで、最初の列はPIDであり、2番目の列は各スレッドのLinuxスレッドIDを示しています。
5. 結論
この記事では、Javaアプリケーションのスレッド数を見つける方法がいくつかあることを確認しました。 ほとんどの場合、topコマンドやpsコマンドなどのコマンドラインオプションを使用するのが一般的な方法です。
ただし、状況によっては、JavaVisualVMなどのグラフィカルツールも必要になる場合があります。 すべてのコードサンプルは、GitHubでから入手できます。