Ottieni un elenco di tutti i thread attualmente in esecuzione in Java
C'è un modo per ottenere un elenco di tutti i thread in esecuzione nella JVM corrente (inclusi i thread NON avviati dalla mia classe)?
È anche possibile ottenere gli oggetti Thread e Class di tutti i Thread nell'elenco?
Voglio essere in grado di farlo attraverso il codice.
12 answers
Per ottenere un set iterabile:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Per convertirlo in un array:
Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);
Ottieni un handle alla radice ThreadGroup
, in questo modo:
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
Ora, chiamare ripetutamente la funzione enumerate()
sul gruppo radice. Il secondo argomento consente di ottenere tutti i thread, in modo ricorsivo:
Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true ) == threads.length) {
threads = new Thread[threads.length * 2];
}
Nota come chiamiamo enumerate() ripetutamente fino a quando l'array è abbastanza grande da contenere tutte le voci.
Sì, dai un'occhiata a ottenendo un elenco di thread. Un sacco di esempi su quella pagina.
Questo per farlo a livello di programmazione. Se vuoi solo una lista su Linux almeno puoi usare questo comando:
kill -3 processid
E la VM eseguirà un dump del thread su stdout.
È possibile ottenere molte informazioni sui thread dal ThreadMXBean.
Chiama la funzione di gestione statica .getThreadMXBean () metodo per ottenere un riferimento al MBean.
Hai dato un'occhiata a jconsole ?
Questo elencherà tutti i thread in esecuzione per un particolare processo Java.
È possibile avviare jconsole dalla cartella JDK bin.
È anche possibile ottenere una traccia completa dello stack per tutti i thread premendo Ctrl+Break
in Windows o inviando kill pid --QUIT
in Linux.
In Groovy puoi chiamare metodi privati
// Get a snapshot of the list of all threads
Thread[] threads = Thread.getThreads()
In Java, è possibile richiamare tale metodo utilizzando reflection a condizione che security manager lo consenta.
Nella console java, premere Ctrl-Break. Elencherà tutti i thread più alcune informazioni sull'heap. Questo non ti darà accesso agli oggetti, naturalmente. Ma può essere molto utile per il debug comunque.
Puoi provare qualcosa del genere:
Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));
E ovviamente puoi ottenere più caratteristiche del thread se ne hai bisogno.
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 + " ");
}
}
Snippet di codice per ottenere l'elenco dei thread avviati dal thread principale:
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();
}
}
}
Uscita:
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
Se hai bisogno di tutti i thread, inclusi i thread di sistema, che non sono stati avviati dal tuo programma, rimuovi sotto condizione.
if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())
Ora in uscita:
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
Gli utenti di Apache commons possono usare ThreadUtils. L'implementazione corrente utilizza l'approccio walk the thread group precedentemente descritto.
for (Thread t : ThreadUtils.getAllThreads()) {
System.out.println(t.getName() + ", " + t.isDaemon());
}