Est-il possible d'obtenir une liste de tous les threads en cours d'exécution dans la JVM actuelle (y compris les threads non démarrés par ma classe)?
Est-il également possible d'obtenir les objets Thread et Class de tous les Thread de la liste?
Je veux être capable de faire cela avec du code.
Pour obtenir un ensemble itérable:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Obtenez un handle vers la racine ThreadGroup
, comme ceci:
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
Maintenant, appelez la fonction enumerate()
sur le groupe racine à plusieurs reprises. Le second argument vous permet d'obtenir tous les threads, de manière récursive:
Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true ) == threads.length) {
threads = new Thread[threads.length * 2];
}
Notez comment nous appelons enumerate () à plusieurs reprises jusqu'à ce que le tableau soit suffisamment grand pour contenir toutes les entrées.
Oui, jetez un oeil à obtenir une liste de discussions . Beaucoup d'exemples sur cette page.
C'est pour le faire par programme. Si vous voulez juste une liste sur Linux au moins, vous pouvez simplement utiliser cette commande:
kill -3 processid
et le VM fera un dump de thread sur stdout.
Vous pouvez obtenir beaucoup d'informations sur les threads à partir de ThreadMXBean .
Appelez la méthode statique ManagementFactory.getThreadMXBean () pour obtenir une référence au MBean.
Avez-vous jeté un œil à jconsole ?
Cela listera tous les threads en cours d'exécution pour un processus Java particulier.
Vous pouvez lancer jconsole à partir du dossier JDK bin.
Vous pouvez également obtenir une trace complète de la pile pour tous les threads en cliquant sur Ctrl+Break
sous Windows ou en envoyant kill pid --QUIT
sous Linux.
Dans Groovy vous pouvez appeler des méthodes privées
// Get a snapshot of the list of all threads
Thread[] threads = Thread.getThreads()
Dans Java , vous pouvez appeler cette méthode à l'aide de la réflexion, à condition que le gestionnaire de sécurité le permette.
Vous pouvez essayer quelque chose comme ça:
Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));
et vous pouvez évidemment obtenir plus de caractéristiques de fil si vous en avez besoin.
Extrait de code permettant d'obtenir la liste des threads démarrés par le thread principal:
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();
}
}
}
sortie:
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
Si vous avez besoin de tous les threads, y compris les threads système, qui n'ont pas été démarrés par votre programme, supprimez la condition ci-dessous.
if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())
Maintenant sortie:
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
Dans la console Java, appuyez sur Ctrl-Break . Il listera tous les threads plus quelques informations sur le tas. Cela ne vous donnera évidemment pas accès aux objets. Mais cela peut quand même être très utile pour le débogage.
Les utilisateurs d’Apache Commons peuvent utiliser ThreadUtils
. L'implémentation actuelle utilise l'approche de groupe de discussion décrite précédemment.
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 + " ");
}
}
Pour obtenir la liste des threads et de leurs états complets à l'aide de terminal, vous pouvez utiliser la commande ci-dessous:
jstack -l <PID>
Quel PID est l'id du processus en cours d'exécution sur l'ordinateur. Pour obtenir l'ID de processus de votre processus Java, vous pouvez simplement exécuter la commande ci-dessous:
jsp
Vous pouvez également analyser le vidage de threads généré par jstack dans des TDA (analyseurs de vidage de threads) tels que fastthread ou outil d'analyse de thread Spotify .