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

Kry*_*ten 221 java multithreading jvm

有没有什么办法可以获得当前JVM中所有正在运行的Thread的列表(包括我的类未启动的Threads)?

是否也可以在列表中获取所有Thread的Thread和Class对象?

我希望能够通过代码完成此操作.

the*_*lfe 299

要获得可迭代集:

Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Run Code Online (Sandbox Code Playgroud)

  • @Eddie这是一个常识的假设,还是你做过实验?你说的"慢得多"; 多慢?这值得么?我质疑为了提高效率而使代码变得更糟的任何尝试.如果你有一个效率要求_和_一个定量衡量效率的基础设施,那么我可以让人们让代码变得更糟,因为他们似乎知道他们在做什么.根据Donald Knuth的说法,参见[万恶之源](http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize). (28认同)
  • 我没有计时这些特定的替代方案,但我已经使用其他Java方法来收集堆栈跟踪而不仅仅是一个线程列表.性能影响似乎非常依赖于您正在使用的JVM(例如JRockit vs Sun JVM).值得在您的具体实例中进行测量.它是否会影响您取决于您​​的JVM选择以及您拥有的线程数.我发现通过ThreadMXBean.dumpAllThreads获取所有堆栈跟踪大约250个线程需要150 - 200毫秒,同时只获得线程列表(没有跟踪)无法测量(0毫秒). (19认同)
  • 虽然比提出的其他替代方案更清洁,但这会产生降低所有线程的堆栈跟踪成本的缺点.如果您仍将使用这些堆栈跟踪,这显然是优越的.如果没有,那么除了干净的代码之外,这可能会明显变慢,没有任何收益. (18认同)
  • @thejoshwolfe:当然,可读性是一个重要因素,不应该进行微观优化等.但是,我在编写一个小型应用程序性能监视器时进行了研究.对于这种工具,最小性能印记对于获得可靠数据至关重要,因此我选择了无堆栈跟踪方法. (5认同)
  • 在我的系统(Oracle Java 1.7 VM)上,快速检查显示此方法比下面的替代方法快~70..80倍.堆栈跟踪和反射属于最重的Java操作. (4认同)

Fre*_*abe 71

获取root的句柄ThreadGroup,如下所示:

ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
    rootGroup = parentGroup;
}
Run Code Online (Sandbox Code Playgroud)

现在,enumerate()重复调用根组上的函数.第二个参数允许您以递归方式获取所有线程:

Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true ) == threads.length) {
    threads = new Thread[threads.length * 2];
}
Run Code Online (Sandbox Code Playgroud)

注意我们如何反复调用enumerate(),直到数组足够大以包含所有条目.

  • 我很震惊这个策略在互联网上如此受欢迎.[我的策略](http://stackoverflow.com/questions/1323408/get-a-list-of-all-threads-currently-running-in-java/3018672#3018672)更简单(1行代码)并且还可以避免竞争条件. (22认同)
  • +1这个被低估的答案,因为它更适合监控目的恕我直言.其固有的竞争条件在监控方面并不重要.然而,正如一些quick'n'dirty测试显示的那样,它比基于堆栈跟踪的解决方案快约70-80倍.对于监控,一个小的性能印记是必不可少的,因为你要保持对受监控系统的影响尽可能小(Heisenberg再次敲击:)对于调试,你可能需要更可靠的信息,stacktrace方法可能是必要.顺便说一句,MxBean解决方案比使用堆栈跟踪更慢. (18认同)
  • @thejoshwolfe:实际上,我同意 - 我认为你的答案要好得多,如果它不会迟到一年,它可能会成为首先接受的答案.如果OP仍然经常光顾SO,他显然这样做,他建议不接受我的回答而是接受你的回答. (11认同)
  • @thejoshwolfe我想这个解决方案要便宜得多. (7认同)
  • @thejoshwolfe你的结果不适用于java 1.4 (3认同)
  • 注意除了rootGroup以外的任何东西,都应该使用new Thread [rootGroup.activeCount()+ 1]。activeCount()可以为零,如果为零,则将陷入无限循环。 (2认同)

cle*_*tus 28

是的,看一下获取线程列表.该页面上有很多例子.

这是以编程方式进行的.如果你只想在Linux上找到一个列表,至少可以使用这个命令:

kill -3 processid
Run Code Online (Sandbox Code Playgroud)

并且VM将对stdout执行线程转储.

  • 杀-3?至少在我的linux上,这是"终端退出".杀死,没有列出. (5认同)
  • cletus确实是正确的 - 无论信号是什么意思,kill -3都会将转储线程转移到stdout.我会考虑使用jstack代替. (5认同)

Dan*_*yer 18

您可以从ThreadMXBean获取有关线程的大量信息.

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


pjp*_*pjp 14

你看过jconsole吗?

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

您可以从JDK bin文件夹启动jconsole.

您还可以通过Ctrl+Break在Windows中或kill pid --QUIT在Linux中发送来获取所有线程的完整堆栈跟踪.

  • 嗯,当这个家伙说他想要一个程序化的解决方案时,为什么人们会投票呢? (3认同)

ger*_*rdw 9

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

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


Jar*_*zki 5

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

// Get a snapshot of the list of all threads 
Thread[] threads = Thread.getThreads()
Run Code Online (Sandbox Code Playgroud)

Java中,您可以使用安全管理器允许的反射来调用该方法.


小智 5

您可以尝试如下操作:

Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));
Run Code Online (Sandbox Code Playgroud)

并且显然可以根据需要获得更多线程特征。


Rav*_*abu 5

获取主线程启动的线程列表的代码片段:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

如果您需要包括系统线程在内的所有线程,但这些线程尚未由您的程序启动,请删除以下条件。

if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())
Run Code Online (Sandbox Code Playgroud)

现在输出:

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
Run Code Online (Sandbox Code Playgroud)


Ami*_*ati 5

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

jstack -l <PID>
Run Code Online (Sandbox Code Playgroud)

<PID>是在您的计算机上运行的进程的 ID。要获取 Java 进程的进程 ID,您只需运行该jps命令即可。

此外,您可以在 TDA(线程转储分析器)中分析由 jstack 生成的线程转储,例如fastthreadspotify 线程分析器工具