Risposte:
Per ottenere un set iterabile:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Ottieni un handle per il root ThreadGroup
, in questo modo:
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
Ora chiama enumerate()
ripetutamente la funzione sul gruppo radice. Il secondo argomento ti 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.
rootGroup
, è necessario utilizzare new Thread[rootGroup.activeCount()+1]
. activeCount()
potrebbe essere zero e, se lo è, ti imbatterai in un ciclo infinito.
Sì, dai un'occhiata a ottenere un elenco di thread . Molti esempi su quella pagina.
Questo è farlo programmaticamente. Se vuoi solo un elenco su Linux almeno puoi semplicemente usare questo comando:
kill -3 processid
e la VM eseguirà un dump del thread su stdout.
Puoi ottenere molte informazioni sui thread da ThreadMXBean .
Chiamare il metodo statico ManagementFactory.getThreadMXBean () per ottenere un riferimento all'MBean.
Hai dato un'occhiata a jconsole ?
Questo elencherà tutti i thread in esecuzione per un particolare processo Java.
È possibile avviare jconsole dalla cartella bin JDK.
Puoi anche ottenere una traccia dello stack completo per tutti i thread colpendo Ctrl+Break
in Windows o inviando kill pid --QUIT
in Linux.
Gli utenti di Apache Commons possono utilizzare ThreadUtils
. L'implementazione corrente utilizza l'approccio walk the thread group precedentemente delineato.
for (Thread t : ThreadUtils.getAllThreads()) {
System.out.println(t.getName() + ", " + t.isDaemon());
}
In Groovy puoi chiamare metodi privati
// Get a snapshot of the list of all threads
Thread[] threads = Thread.getThreads()
In Java , è possibile richiamare quel metodo usando reflection a condizione che il gestore della sicurezza lo consenta.
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();
}
}
}
produzione:
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 sono necessari tutti i thread, inclusi i thread di sistema, che non sono stati avviati dal programma, rimuovere la condizione seguente.
if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())
Ora 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
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 + " ");
}
}
Per ottenere un elenco di thread e dei loro stati completi utilizzando il terminale, è possibile utilizzare il comando seguente:
jstack -l <PID>
Quale PID è l'id del processo in esecuzione sul tuo computer. Per ottenere l'id di processo del tuo processo java puoi semplicemente eseguire il jps
comando.
Inoltre, puoi analizzare il tuo dump del thread prodotto da jstack in TDA (Thread Dump Analyzer) come strumento di analisi del thread fastthread o spotify .