2009-08-24 10 views
177

Gibt es eine Möglichkeit, eine Liste aller laufenden Threads in der aktuellen JVM zu erhalten (einschließlich der Threads, die NICHT von meiner Klasse gestartet wurden)?Erhalte eine Liste aller laufenden Threads in Java

Ist es auch möglich, die Thread- und Klassenobjekte aller Threads in der Liste zu erhalten?

Ich möchte dies durch Code tun können.

Antwort

251

Um eine iterable Set zu erhalten:

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

Um es in ein Array zu umwandeln:

Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]); 
+15

Obwohl viel sauberer als die andere vorgeschlagene Alternative, hat dies den Nachteil, dass die Kosten für das Erhalten von Stack-Traces für alle Threads entstehen. Wenn Sie diese Stack-Spuren trotzdem verwenden, ist dies eindeutig besser. Wenn nicht, dann kann dies wesentlich langsamer sein, wenn es keinen anderen Gewinn als sauberen Code gibt. – Eddie

+25

@Eddie Ist das eine Annahme aus dem gesunden Menschenverstand oder hast du Experimente gemacht? "deutlich langsamer" sagst du; Wie viel langsamer? Ist es das wert? Ich stelle jeden Versuch in Frage, den Code im Interesse der Effizienz schlechter zu machen. Wenn Sie eine Effizienzanforderung und eine Infrastruktur haben, um die Effizienz quantitativ zu messen, dann bin ich damit einverstanden, dass Leute Code schlechter machen, weil sie zu wissen scheinen, was sie tun. Siehe [die Wurzel allen Übels] (http: //en.wikipedia.org/wiki/Programmoptimierung # When_to_optimize) nach Donald Knuth. – thejoshwolfe

+18

Ich habe diese spezifischen Alternativen nicht zeitlich festgelegt, aber ich habe mit anderen Java-Mitteln gearbeitet, um Stack-Traces zu sammeln, anstatt nur eine Liste von Threads. Die Auswirkungen auf die Performance scheinen sehr stark davon abhängig zu sein, welche JVM Sie verwenden (JRockit vs Sun JVM zum Beispiel). Es lohnt sich, in Ihrer spezifischen Instanz zu messen. Ob Sie davon betroffen sind oder nicht, hängt von Ihrer JVM-Auswahl und davon ab, wie viele Threads Sie haben. Ich fand, dass alle Stack-Traces über ThreadMXBean.dumpAllThreads für etwa 250 Threads 150 - 200 ms benötigten, während nur die Liste der Threads (ohne Traces) nicht messbar war (0 ms). – Eddie

24

Ja, werfen Sie einen Blick auf getting a list of threads. Viele Beispiele auf dieser Seite.

Das ist programmgesteuert zu tun. Wenn Sie nur eine Liste auf Linux zumindest möchten, können Sie einfach diesen Befehl verwenden:

kill -3 processid 

und die VM einen Thread-Dump zu stdout tun.

+5

töten -3? Zumindest auf meinem Linux, das ist "terminal quit". Kills, listet nicht auf. – khedron

+5

Cletus ist in der Tat richtig - ein Kill-3 wird Thread-Dump zu stdout, unabhängig davon, was das Signal bedeuten soll. Ich würde stattdessen JStack verwenden. –

10

Haben Sie einen Blick auf jconsole geworfen?

Dies listet alle Threads auf, die für einen bestimmten Java-Prozess ausgeführt werden.

Sie können jconsole über den Ordner JDK bin starten.

Sie können auch eine vollständige Stack-Trace für alle Threads erhalten, indem Sie in Windows Ctrl+Break schlagen oder kill pid --QUIT in Linux senden.

+0

Ich möchte auf die Liste innerhalb meiner Java-Klasse zugreifen – Kryten

+0

In diesem Fall sehen Sie sich die Antwort von Cletus an. – pjp

+3

Ähm, warum wählen die Leute das, wenn der Typ sagt, er wolle eine programmatische Lösung? – cletus

62

Erhalten Sie einen Griff an der Wurzel Thread, wie folgt aus:

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

Nun rufen Sie die enumerate() Funktion auf der Root-Gruppe wiederholt. Das zweite Argument können Sie alle Fäden erhalten, rekursiv:

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

Hinweis, wie wir aufzählen() aufrufen, so oft, bis das Array groß genug ist, um alle Einträge zu enthalten.

+19

Ich bin schockiert, dass diese Strategie im Internet so beliebt ist. [Meine Strategie] (http://stackoverflow.com/questions/1323408/get-a-list-of-all-threads-current-ly-running-in-java/3018672#3018672) ist viel einfacher (1 Zeile Code) und funktioniert genauso gut mit dem zusätzlichen Bonus der Vermeidung von Rennen Bedingungen. – thejoshwolfe

+9

@thejoshwolfe: Eigentlich stimme ich zu - ich denke, Ihre Antwort ist viel besser, und es wäre wahrscheinlich die akzeptierte Antwort in erster Linie, wenn es nicht ein Jahr zu spät gewesen wäre. Wenn der OP immer noch SO besucht, was er anscheinend tut, wäre er gut beraten, meine Antwort zu akzeptieren und eher Ihre anzunehmen. –

+3

@thejoshwolfe Ihre resulotion wird nicht mit Java arbeiten 1.4 – fnobbi

3

In der Java-Konsole, drücken Sie Ctrl-Break. Es werden alle Threads und einige Informationen über den Heap aufgelistet. Dadurch erhalten Sie natürlich keinen Zugriff auf die Objekte. Aber es kann für das Debugging sowieso sehr hilfreich sein.

14

Sie können eine Menge Informationen über Threads von der ThreadMXBean erhalten.

Rufen Sie die statische Methode ManagementFactory.getThreadMXBean() auf, um einen Verweis auf die MBean zu erhalten.

+1

Ich mag das. Es scheint die sauberste und am meisten "API-unterstützte" Methode zu sein –

2
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 + " "); 
     } 
    } 
4

In Groovy Sie private Methoden

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

nennen In Java, Sie können diese Methode mithilfe der Reflektion aufrufen, sofern der Sicherheitsmanager dies zulässt.

2

Sie können so etwas wie dies versuchen:

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

und Sie können natürlich mehr Thread Charakteristik erhalten, wenn Sie benötigen.

1

Code-Snippet Liste der Themen von Haupt-Thread zu erhalten begonnen:

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(); 
     } 
    } 
} 

Ausgang:

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 

Wenn Sie alle Themen benötigen, einschließlich System-Threads, die von Ihrem Programm nicht gestartet haben, Unter Bedingung entfernen.

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

Jetzt Ausgabe:

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 
Verwandte Themen