获取当前在Java中运行的所有线程的列表

是否有任何方法可以获得当前JVM中所有运行线程的列表(包括线程由我的类启动)?

是否也可以获得列表中所有线程的ThreadClass对象?

我希望能够通过代码来实现。

257319 次浏览

是的,看看获取线程列表。那页上有很多例子。

这是通过编程来实现的。如果你只是想在Linux上得到一个列表,至少你可以使用这个命令:

kill -3 processid

虚拟机将做一个线程转储到标准输出。

你看过jconsole吗?

这将列出为特定Java进程运行的所有线程。

可以从JDK bin文件夹启动jconsole。

你也可以通过在Windows中点击Ctrl+Break或在Linux中发送kill pid --QUIT来获得所有线程的完整堆栈跟踪。

获取根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(),直到数组大到足以包含所有条目。

在java控制台中,点击Ctrl-Break。它将列出所有线程以及堆的一些信息。当然,这不会让您访问对象。但无论如何,它对调试都很有帮助。

你可以从ThreadMXBean中获得很多关于线程的信息。

调用静态ManagementFactory.getThreadMXBean ()方法来获取对MBean的引用。

    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 + "  ");
}
}

获取一个可迭代集:

Set<Thread> threadSet = Thread.getAllStackTraces().keySet();

性能:0毫秒,12个线程(Azul JVM 16.0.1, Windows 10, Ryzen 5600X)。

Groovy中,你可以调用私有方法

// Get a snapshot of the list of all threads
Thread[] threads = Thread.getThreads()

Java中,只要安全管理器允许,您可以使用反射调用该方法。

你可以使用getAllThreadIds返回所有活动线程id。当此方法返回时,返回数组中包含的某些线程可能已经终止。

ManagementFactory.getThreadMXBean().getAllThreadIds()

你可以尝试这样做:

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

Apache Commons用户可以使用ThreadUtils。当前实现使用前面概述的线程组方法。

for (Thread t : ThreadUtils.getAllThreads()) {
System.out.println(t.getName() + ", " + t.isDaemon());
}

要使用终端获取线程列表及其完整状态,您可以使用下面的命令:

jstack -l <PID>

其中<PID>是在您的计算机上运行的进程的id。要获得您的java进程的进程id,您可以简单地运行jps命令。

此外,你可以在TDAs(线程转储分析器)中分析jstack生成的线程转储,例如fastthreadSpotify线程分析工具