Ответ 1
Чтобы получить повторяемый набор:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Можно ли каким-то образом получить список всех запущенных потоков в текущей JVM (включая потоки, не запущенные моим классом)?
Можно ли также получить объекты Thread
и Class
всех потоков в списке?
Я хочу быть в состоянии сделать это с помощью кода.
Чтобы получить повторяемый набор:
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
и VM выполнит сброс потока в stdout.
Вы можете получить много информации о потоках из ThreadMXBean.
Вызовите статический метод ManagementFactory.getThreadMXBean(), чтобы получить ссылку на MBean.
Вы взглянули на jconsole?
Здесь будут перечислены все потоки, выполняемые для определенного процесса Java.
Вы можете запустить jconsole из папки JDK bin.
Вы также можете получить полную трассировку стека для всех потоков, нажав Ctrl+Break
в Windows или отправив kill pid --QUIT
в Linux.
Пользователи Apache Commons могут использовать ThreadUtils
. В текущей реализации используется подход, основанный на обходе группы потоков, описанный ранее.
for (Thread t : ThreadUtils.getAllThreads()) {
System.out.println(t.getName() + ", " + t.isDaemon());
}
В Groovy вы можете вызвать частные методы
// Get a snapshot of the list of all threads
Thread[] threads = Thread.getThreads()
В Java вы можете вызвать этот метод с использованием отражения, если это позволяет диспетчер безопасности.
Вы можете попробовать что-то вроде этого:
Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));
и вы можете, очевидно, получить больше характеристик потока, если вам нужно.
Фрагмент кода для получения списка потоков, запущенных главным образом:
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
В консоли 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 + " ");
}
}
Чтобы получить список потоков и их полных состояний с помощью терминала, вы можете использовать команду ниже:
jstack -l <PID>
Какой PID является идентификатором процесса, запущенного на вашем компьютере. Чтобы получить идентификатор процесса вашего Java-процесса, вы можете просто запустить следующую команду:
jps
Кроме того, вы можете анализировать дамп потока, созданный jstack, в TDA (Thread Dump Analyzer), например, fastthread или инструмент анализатора спойтов потока.