【发布时间】:2009-08-24 16:30:11
【问题描述】:
有什么办法可以得到当前JVM中所有正在运行的线程的列表(包括我的类未启动的线程)?
是否也可以获取列表中所有线程的Thread和Class对象?
我希望能够通过代码做到这一点。
【问题讨论】:
标签: java multithreading jvm
有什么办法可以得到当前JVM中所有正在运行的线程的列表(包括我的类未启动的线程)?
是否也可以获取列表中所有线程的Thread和Class对象?
我希望能够通过代码做到这一点。
【问题讨论】:
标签: java multithreading jvm
要获得一个可迭代的集合:
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
性能:12 个线程(Azul JVM 16.0.1、Windows 10、Ryzen 5600X)为 0 毫秒。
【讨论】:
获取根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() 直到数组大到可以包含所有条目。
【讨论】:
rootGroup 以外的任何内容,您应该使用new Thread[rootGroup.activeCount()+1]。 activeCount() 可能为零,如果是,您将陷入无限循环。
是的,看看getting a list of threads。该页面上有很多示例。
这是以编程方式进行的。如果你至少想要一个 Linux 上的列表,你可以使用这个命令:
kill -3 processid
VM 会做一个线程转储到标准输出。
【讨论】:
您可以从ThreadMXBean 获得很多关于线程的信息。
调用静态ManagementFactory.getThreadMXBean() 方法获取对MBean 的引用。
【讨论】:
你看过jconsole吗?
这将列出为特定 Java 进程运行的所有线程。
您可以从 JDK bin 文件夹中启动 jconsole。
您还可以通过在 Windows 中点击 Ctrl+Break 或在 Linux 中发送 kill pid --QUIT 来获取所有线程的完整堆栈跟踪。
【讨论】:
你可以试试这样的:
Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));
如果你需要,你显然可以获得更多的线程特性。
【讨论】:
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 中,只要安全管理器允许,您就可以使用反射调用该方法。
【讨论】:
代码 sn-p 获取主线程启动的线程列表:
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
【讨论】:
要使用终端获取线程列表及其完整状态,您可以使用以下命令:
jstack -l <PID>
<PID> 是您计算机上运行的进程的 ID。要获取您的 java 进程的进程 ID,您只需运行 jps 命令即可。
此外,您还可以在 TDA(线程转储分析器)中分析 jstack 生成的线程转储,例如 fastthread 或 spotify thread analyzer tool。
【讨论】:
在 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 + " ");
}
}
【讨论】:
您可以使用返回所有活动线程 ID 的 getAllThreadIds。此方法返回时,返回的数组中包含的某些线程可能已终止。
ManagementFactory.getThreadMXBean().getAllThreadIds()
【讨论】: