現在Javaで実行されているすべてのスレッドのリストを取得する


232

現在のJVMで実行中のすべてのスレッド(自分のクラスで開始されていないスレッドを含む)のリストを取得する方法はありますか?

リスト内のすべてのスレッドのThreadおよびClassオブジェクトを取得することもできますか?

これをコードで実行できるようにしたい。

回答:


325

反復可能なセットを取得するには:

Set<Thread> threadSet = Thread.getAllStackTraces().keySet();

19
提案された他の代替案よりもはるかにクリーンですが、これにはすべてのスレッドのスタックトレースを取得するコストがかかるという欠点があります。とにかくこれらのスタックトレースを使用する場合、これは明らかに優れています。そうでない場合、クリーンなコード以外の利点がないため、これは大幅に遅くなる可能性があります。
エディ

29
@エディそれは常識からの仮定ですか、それとも実験をしましたか?「かなり遅い」とあなたは言う。どれくらい遅い?その価値はありますか?効率を上げるためにコードを悪化させようとする試みには疑問があります。効率の要件効率を定量的に測定するためのインフラストラクチャがある場合、私は人々が何をしているのかを知っているように見えるので、人々がコードを悪化させても大丈夫です。ドナルド・クヌースによると、すべての悪の根源を参照してください。
thejoshwolfe

20
私はこれらの特定の代替手段の時間を計測していませんが、私はスタックトレースを収集する他のJavaの方法ではなく、単なるスレッドのリストを扱ってきました。パフォーマンスへの影響は、使用しているJVM(JRockitとSun JVMなど)に大きく依存しているようです。特定のインスタンスで測定する価値があります。それがユーザーに影響するかどうかは、JVMの選択とスレッドの数に依存します。ThreadMXBean.dumpAllThreadsを介してすべてのスタックトレースを取得すると、約250スレッドで150〜200ミリ秒かかりますが、スレッドのリスト(トレースなし)だけを取得すると測定不能(0ミリ秒)になることがわかりました。
エディ

4
私のシステム(Oracle Java 1.7 VM)では、簡単なチェックで、この方法が以下の方法よりも70..80倍遅いことが示されています。スタックトレースとリフレクションは、最も重いJava操作に属します。
Franz D.

5
@thejoshwolfe:もちろん、読みやすさは重要な要素であり、マイクロ最適化などを行うべきではありません。しかし、私は小さなアプリケーションパフォーマンスモニターを作成しているときに調査を行いました。この種のツールでは、信頼性の高いデータを取得するために最小限のパフォーマンスインプリントが不可欠であるため、スタックトレースを使用しない方法を選択しました。
Franz D.

75

次のThreadGroupように、rootへのハンドルを取得します。

ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
    rootGroup = parentGroup;
}

ここでenumerate()、ルートグループの関数を繰り返し呼び出します。2番目の引数では、すべてのスレッドを再帰的に取得できます。

Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true ) == threads.length) {
    threads = new Thread[threads.length * 2];
}

配列がすべてのエントリを格納するのに十分な大きさになるまで、enumerate()を繰り返し呼び出す方法に注意してください。


22
この戦略がインターネット上で非常に人気があることに私はショックを受けました。私の戦略ははるかに単純(コード1行)で、競合状態を回避するという追加のボーナスと同じように機能します。
thejoshwolfe 2011

11
@thejoshwolfe:実際、私は同意します-あなたの答えははるかに優れていると思います。1年遅れていなければ、そもそも受け入れられた答えだったでしょう。OPがまだSOに頻繁に参加している場合は、彼がそうしているように見えますが、私の答えを受け入れずに、むしろあなたの答えを受け入れるようにアドバイスされます。
Frerich Raabe、

2
以外の場合はrootGroup、を使用する必要があることに注意してくださいnew Thread[rootGroup.activeCount()+1]activeCount()ゼロになる可能性があり、ゼロの場合は無限ループに陥ります。
jmiserez 14

7
@thejoshwolfeこのソリューションははるかに安価だと思います。
Haozhun 14

19
この過小評価された回答の+1。これは、IMHOの監視目的にはるかに適しています。監視では、その固有の競合状態はあまり問題になりません。ただし、いくつかのクイックアンドダーティテストが示したように、スタックトレースベースのソリューションよりも約70〜80倍高速です。監視には、監視対象システムへの影響を可能な限り小さくしたいので、小さなパフォーマンスインプリントが不可欠です(ハイゼンベルグが再び警告します)デバッグの場合、より信頼できる情報が必要な場合は、スタックトレースメソッドを使用できます。必須。ところで、MxBeanソリューションはスタックトレースを使用するよりもさらに低速です。
Franz D.

29

はい、スレッドのリストの取得をご覧ください。そのページにはたくさんの例があります。

それはプログラムで行うことです。少なくともLinuxのリストが必要な場合は、次のコマンドを使用できます。

kill -3 processid

VMはstdoutにスレッドダンプを実行します。


5
-3を殺す?少なくとも私のLinuxでは、これは「ターミナルの終了」です。殺し、リストしていません。
マイケルH.

5
cletusは確かに正しい-kill -3は、シグナルの意味に関係なく、dumpをstdoutにスレッド化します。代わりにjstackの使用を検討します。
Dan Hardiker、2014

スレッドのリストを取得できません:nadeausoftware.comが接続を拒否しました。
DSlomer64


14

あなたは見てとったJConsoleの

これにより、特定のJavaプロセスで実行されているすべてのスレッドがリストされます。

jconsoleはJDK binフォルダーから起動できます。

Ctrl+BreakWindowsでヒットするかkill pid --QUIT、Linuxで送信することにより、すべてのスレッドの完全なスタックトレースを取得することもできます。


私のJavaクラス内のリストにアクセスしたい
Kryten

その場合はクレタスの答えを見てください。
pjp 2009

3
ええと、なぜ彼がプログラムによる解決策を望んでいると言ったときに、人々はこれを投票しているのですか?
cletus 2009

質問はそれを述べていないので。質問が明確になるように編集します。
PJP

8

Apache Commonsユーザーはを使用できますThreadUtils。現在の実装では、前述のウォークスレッドグループアプローチを使用しています。

for (Thread t : ThreadUtils.getAllThreads()) {
      System.out.println(t.getName() + ", " + t.isDaemon());
}

7

あなたはこのようなことを試すことができます:

Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));

必要に応じて、スレッドの特性を明らかに向上させることができます。


5

Groovyでは、プライベートメソッドを呼び出すことができます。

// Get a snapshot of the list of all threads 
Thread[] threads = Thread.getThreads()

ではJavaのは、セキュリティマネージャがそれを可能にすることを提供するリフレクションを使用して、そのメソッドを呼び出すことができます。


エラーが発生し、スレッドに対してgetThreadsが定義されていません。そして、私はドキュメントでこの関数を見ません。

4

メインスレッドによって開始されたスレッドのリストを取得するコードスニペット:

import java.util.Set;

public class ThreadSet {
    public static void main(String args[]) throws Exception{
        Thread.currentThread().setName("ThreadSet");
        for ( int i=0; i< 3; i++){
            Thread t = new Thread(new MyThread());
            t.setName("MyThread:"+i);
            t.start();
        }
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        for ( Thread t : threadSet){
            if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup()){
                System.out.println("Thread :"+t+":"+"state:"+t.getState());
            }
        }
    }
}

class MyThread implements Runnable{
    public void run(){
        try{
            Thread.sleep(5000);
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

出力:

Thread :Thread[MyThread:2,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:0,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:1,5,main]:state:TIMED_WAITING
Thread :Thread[ThreadSet,5,main]:state:RUNNABLE

プログラムによって開始されていない、システムスレッドを含むすべてのスレッドが必要な場合は、以下の条件を削除してください。

if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())

今出力:

Thread :Thread[MyThread:2,5,main]:state:TIMED_WAITING
Thread :Thread[Reference Handler,10,system]:state:WAITING
Thread :Thread[MyThread:1,5,main]:state:TIMED_WAITING
Thread :Thread[ThreadSet,5,main]:state:RUNNABLE
Thread :Thread[MyThread:0,5,main]:state:TIMED_WAITING
Thread :Thread[Finalizer,8,system]:state:WAITING
Thread :Thread[Signal Dispatcher,9,system]:state:RUNNABLE
Thread :Thread[Attach Listener,5,system]:state:RUNNABLE

3
    public static void main(String[] args) {


        // Walk up all the way to the root thread group
        ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
        ThreadGroup parent;
        while ((parent = rootGroup.getParent()) != null) {
            rootGroup = parent;
        }

        listThreads(rootGroup, "");
    }


    // List all threads and recursively list all subgroup
    public static void listThreads(ThreadGroup group, String indent) {
        System.out.println(indent + "Group[" + group.getName() + 
                ":" + group.getClass()+"]");
        int nt = group.activeCount();
        Thread[] threads = new Thread[nt*2 + 10]; //nt is not accurate
        nt = group.enumerate(threads, false);

        // List every thread in the group
        for (int i=0; i<nt; i++) {
            Thread t = threads[i];
            System.out.println(indent + "  Thread[" + t.getName() 
                    + ":" + t.getClass() + "]");
        }

        // Recursively list all subgroups
        int ng = group.activeGroupCount();
        ThreadGroup[] groups = new ThreadGroup[ng*2 + 10];
        ng = group.enumerate(groups, false);

        for (int i=0; i<ng; i++) {
            listThreads(groups[i], indent + "  ");
        }
    }

3

Javaコンソールで、Ctrl-Breakを押します。すべてのスレッドとヒープに関するいくつかの情報がリストされます。もちろん、これではオブジェクトにアクセスできません。しかし、とにかくデバッグに非常に役立ちます。


1

ターミナルを使用してスレッドとその完全な状態のリストを取得するには、次のコマンドを使用できます。

jstack -l <PID>

コンピュータで実行されているプロセスのIDであるPID。JavaプロセスのプロセスIDを取得するには、jpsコマンドを実行するだけです。

また、faststackSpotify スレッドアナライザーツールなどのTDA(Thread Dump Analyzer)でjstackによって生成されたスレッドダンプを分析することもできます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.