Получить список всех потоков, работающих в настоящее время в Java
Можно ли как-нибудь получить список всех запущенных потоков в текущей JVM (включая потоки, которые НЕ были запущены моим классом)?
Можно ли также получить объекты Thread и Class всех потоков в списке?
Я хочу быть в состоянии сделать это с помощью кода.
12 ответов
Чтобы получить повторяемый набор:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Получить ручку в корень ThreadGroup
, как это:
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
Теперь позвоните enumerate()
функция на корневой группе неоднократно. Второй аргумент позволяет получить все потоки рекурсивно:
Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true ) == threads.length) {
threads = new Thread[threads.length * 2];
}
Обратите внимание, как мы неоднократно вызываем enumerate(), пока массив не станет достаточно большим, чтобы содержать все записи.
Да, взгляните на получение списка тем. Много примеров на этой странице.
Это делается программно. Если вы просто хотите получить список в Linux, по крайней мере, вы можете просто использовать эту команду:
kill -3 processid
и виртуальная машина сделает дамп потока в стандартный вывод.
Вы можете получить много информации о потоках из ThreadMXBean.
Вызовите статический метод ManagementFactory.getThreadMXBean(), чтобы получить ссылку на MBean.
Вы смотрели на jconsole?
Это перечислит все потоки, работающие для определенного процесса Java.
Вы можете запустить jconsole из папки bin JDK.
Вы также можете получить полную трассировку стека для всех потоков, нажав Ctrl+Break
в Windows или отправив kill pid --QUIT
в линуксе
Пользователи Apache commons могут использовать ThreadUtils. Текущая реализация использует ранее описанный подход с использованием групповых потоков.
for (Thread t : ThreadUtils.getAllThreads()) {
System.out.println(t.getName() + ", " + t.isDaemon());
}
Вы можете попробовать что-то вроде этого:
Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));
и вы можете, очевидно, получить больше характеристик потока, если вам нужно.
Чтобы получить список потоков и их полные состояния с помощью терминала, вы можете использовать следующую команду:
jstack -l <PID>
Какой PID является идентификатором процесса, запущенного на вашем компьютере. Чтобы получить идентификатор процесса вашего java-процесса, вы можете просто запуститьjps
команда.
Кроме того, вы можете анализировать дамп потока, созданный jstack, в TDA (Thread Dump Analyzer), таком как анализатор потоков fastthread или spotify.
Фрагмент кода, чтобы получить список потоков, запущенных основным потоком:
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();
}
}
}
выход:
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
Если вам нужны все потоки, включая системные, которые не были запущены вашей программой, удалите условие ниже.
if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())
Теперь вывод:
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
В Groovy вы можете вызывать приватные методы
// Get a snapshot of the list of all threads
Thread[] threads = Thread.getThreads()
В Java вы можете вызывать этот метод, используя отражение, если это разрешено диспетчером безопасности.
В консоли Java нажмите Ctrl-Break. Он перечислит все потоки плюс некоторую информацию о куче. Это не даст вам доступ к объектам, конечно. Но это может быть очень полезно для отладки в любом случае.
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 + " ");
}
}