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)?
Ist es auch möglich, die Thread- und Class-Objekte aller Threads in der Liste abzurufen?
Ich möchte dies durch Code tun können.
So erhalten Sie ein iterierbares Set:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Holen Sie sich ein Handle für das Stammverzeichnis ThreadGroup
wie folgt:
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
Rufen Sie nun wiederholt die Funktion enumerate()
für die Stammgruppe auf. Mit dem zweiten Argument können Sie alle Threads rekursiv abrufen:
Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true ) == threads.length) {
threads = new Thread[threads.length * 2];
}
Beachten Sie, wie wir enumerate () wiederholt aufrufen, bis das Array groß genug ist, um alle Einträge zu enthalten.
Ja, werfen Sie einen Blick auf eine Liste der Threads bekommen . Viele Beispiele auf dieser Seite.
Das ist programmatisch zu machen. Wenn Sie nur eine Liste unter Linux möchten, können Sie einfach diesen Befehl verwenden:
kill -3 processid
und die VM erstellt einen Thread-Dump für stdout.
Sie können viele Informationen über Threads im ThreadMXBean erhalten.
Rufen Sie die statische ManagementFactory.getThreadMXBean () - Methode auf, um einen Verweis auf die MBean zu erhalten.
Haben Sie einen Blick auf jconsole geworfen?
Dadurch werden alle Threads aufgelistet, die für einen bestimmten Java-Prozess ausgeführt werden.
Sie können jconsole über den Ordner "JDK bin" starten.
Sie können einen vollständigen Stack-Trace für alle Threads abrufen, indem Sie in Windows Ctrl+Break
drücken oder in Linux kill pid --QUIT
senden.
In Groovy können Sie private Methoden aufrufen
// Get a snapshot of the list of all threads
Thread[] threads = Thread.getThreads()
In Java können Sie diese Methode mithilfe von Reflection aufrufen, sofern der Sicherheitsmanager dies zulässt.
Sie können so etwas 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-Eigenschaften erhalten, wenn Sie brauchen.
Code-Snippet zum Abrufen einer Liste von Threads, die vom Haupt-Thread gestartet wurden:
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();
}
}
}
ausgabe:
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 Threads einschließlich System-Threads benötigen, die nicht von Ihrem Programm gestartet wurden, entfernen Sie die folgende Bedingung.
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
Drücken Sie in der Java-Konsole Ctrl-Break . Es werden alle Threads sowie einige Informationen zum Heap aufgelistet. Dies gibt Ihnen natürlich keinen Zugriff auf die Objekte. Für das Debuggen kann es jedoch sehr hilfreich sein.
Apache Commons-Benutzer können ThreadUtils
verwenden. Die aktuelle Implementierung verwendet den zuvor umrissenen Ansatz für das Durchlaufen der Threadgruppe.
for (Thread t : ThreadUtils.getAllThreads()) {
System.out.println(t.getName() + ", " + t.isDaemon());
}
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 + " ");
}
}
Mit dem folgenden Befehl können Sie eine Liste der Threads und ihrer vollständigen Zustände über das Terminal abrufen:
jstack -l <PID>
Welche PID ist die ID des Prozesses, der auf dem Computer ausgeführt wird. Um die Prozess-ID Ihres Prozesses Java abzurufen, können Sie einfach den folgenden Befehl ausführen:
jsp
Sie können auch Ihren Thread-Dump analysieren, der von jstack in TDAs (Thread Dump Analyzer) erzeugt wurde, wie fastthread oder spotify thread analyzer tool .