Get a list of all threads currently running in Java
Asked Answered
M

13

278

Is there any way I can get a list of all running threads in the current JVM (including the threads not started by my class)?

Is it also possible to get the Thread and Class objects of all threads in the list?

I want to be able to do this through code.

Macnair answered 24/8, 2009 at 16:30 Comment(0)
S
391

To get an iterable set:

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

Performance: 0 ms for 12 threads (Azul JVM 16.0.1, Windows 10, Ryzen 5600X).

Shakitashako answered 10/6, 2010 at 21:28 Comment(13)
While much cleaner than the other alternative proposed, this has the downside of incurring the cost of getting stack traces for all threads. If you will be using those stack traces anyway, this is clearly superior. If not, then this may be significantly slower for no gain other than clean code.Electrical
@Electrical Is that an assumption from common sense, or did you do experiments? "significantly slower" you say; how much slower? Is it worth it? I question any attempt to make code worse for the sake of efficiency. If you have an efficiency requirement and an infrastructure to measure efficiency quantitatively, then I'm ok with people making code worse, because they seem to know what they're doing. See the root of all evil according to Donald Knuth.Shakitashako
I haven't timed these specific alternatives, but I've worked with other Java means of gathering stack traces vs just a list of threads. The performance impact seems to depend very strongly on which JVM you are using (JRockit vs Sun JVM for example). It's worth measuring in your specific instance. Whether or not it will affect you depends on your JVM choice and on how many threads you have. I found that getting all stack traces via ThreadMXBean.dumpAllThreads for about 250 threads to take 150 - 200 msec while getting just the list of threads (without traces) to not be measurable (0 msec).Electrical
On my system (Oracle Java 1.7 VM), a quick check shows that this method is ~70..80 times SLOWER than the alternative below. Stack traces and reflection belong to the heaviest Java operations.Roos
@FranzD., thanks for doing the research. This strategy may not be suitable for all applications, but don't forget about other factors when comparing code. For example, this code that is arguably easier to read and write than a more performant solution. Also, don't forget about the performance penalties built into the Java runtime iteself, such as garbage collection. It may be informative to measure the performance impact in your actual application.Shakitashako
@thejoshwolfe: Of course, readability is an important factor, and one should not micro-optimize etc. However, I did my research while writing a small application performance monitor. For this kind of tool, a minimal performance imprint is essential to get reliable data, so I chose the stacktrace-less method.Roos
Getting a stack trace on HotSpot requires all the threads to reach a safepoint. See "VM Operations and Safepoints": openjdk.java.net/groups/hotspot/docs/RuntimeOverview.htmlAlyssaalyssum
Can someone comment as to whether or not the stacktrace method returns threads that are currently RUNNING, or does it also include threads that are in a TERMINATED state?Ferbam
No working in my Java 8 standalone web application. I did not dig deep why, but it misses a whole bunch of running threads.Schach
I do not agree that the Thread.getAllStackTraces is the right way to go. It asked for set of thread class. While the answer does give that value, it also intermittently get and then throw away stack traces. And it calls the dumpThreads JNI method which has a huge performance penalty, which it does not really need to, since you only need to call the getThreads JNI method in the thread class. This answer is fine for a pre production or test environment but its a bad idea in production and should be actively avoided.Phyllotaxis
Please be respectful of other opinions and the people who criticize you. Calling other solutions "shocked that this strategy is so popular" and Argument from authority for anyone who points out your downside is not a good way to discuss.Paulino
A bit more perf data: 111 threads in a JVM running a Clojure REPL with a multi-threaded app takes 1.14-1.36 ms (95% CI) to enumerate with this method on a 2019 MacBook Pro with AdoptOpenJDK 8.Backwoods
(For comparison, the main alternative method executes in 9.57-10.6 µs in the same REPL that still has 111 threads, so close to two orders of magnitude faster.)Backwoods
F
87

Get a handle to the root ThreadGroup, like this:

ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
    rootGroup = parentGroup;
}

Now, call the enumerate() function on the root group repeatedly. The second argument lets you get all threads, recursively:

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

Note how we call enumerate() repeatedly until the array is large enough to contain all entries.

Fem answered 24/8, 2009 at 16:44 Comment(7)
I'm shocked that this strategy is so popular on the internet. My strategy is way simpler (1 line of code) and works just as well with the added bonus of avoiding race conditions.Shakitashako
@thejoshwolfe: Actually, I agree - I think your answer is much better, and it probably would've been the accepted answer in the first place if it wouldn't have been one year late. If the OP still frequents SO, which he apparently does, he'd be well advised to un-accept my answer and rather accept yours.Fem
Note that for anything other than the rootGroup, you should use new Thread[rootGroup.activeCount()+1]. activeCount() could be zero, and if it is you will run into an infinite loop.Roseannaroseanne
@Shakitashako I suppose this solution is much less expensive.Hl
+1 for this underrated answer, as it is much more suited for monitoring purposes IMHO. Its inherent race conditions do not matter much in monitoring. However, as some quick'n'dirty test showed, it's about 70-80 times faster than the stacktrace-based solution. For monitoring, a small performance imprint is essential, as you you'll want to keep the effects on the monitored system as small as possible (Heisenberg strikes again :) For debugging, where you may need more reliable information, the stacktrace method could be essential. BTW, the MxBean solution is even slower than using stacktraces.Roos
Beware of that in android 5.0 or 5.1,Thread.getAllStackTraces() may cause GC.Canna
One could argue that the authors of org.apache.commons.lang3.ThreadUtils opting for this approach over Thread.getAllStackTraces() for its getSystemThreadGroup() and various findThreads() methods, is a rather prominent endorsement of this answer being best practice.Liberality
F
31

Yes, take a look at getting a list of threads. Lots of examples on that page.

That's to do it programmatically. If you just want a list on Linux at least you can just use this command:

kill -3 processid

and the VM will do a thread dump to stdout.

Fraya answered 24/8, 2009 at 16:31 Comment(3)
kill -3? At least on my linux, that's "terminal quit". Kills, does not list.Ingenious
cletus is indeed correct - a kill -3 will thread dump to stdout, regardless of what the signal is supposed to mean. I would consider using jstack instead.Bodiless
getting a list of threads can’t be reached: nadeausoftware.com refused to connect.Carinthia
O
20

You can get a lot of information about threads from the ThreadMXBean.

Call the static ManagementFactory.getThreadMXBean() method to get a reference to the MBean.

Ous answered 24/8, 2009 at 17:5 Comment(0)
C
15

Have you taken a look at jconsole?

This will list all threads running for a particular Java process.

You can start jconsole from the JDK bin folder.

You can also get a full stack trace for all threads by hitting Ctrl+Break in Windows or by sending kill pid --QUIT in Linux.

Culicid answered 24/8, 2009 at 16:31 Comment(4)
I want to access the list within my java classMacnair
In which case look at cletus' answer.Culicid
Um, why are people voting this up when the guy said he wanted a programmatic solution?Fraya
Because the question doesn't state that. I'll edit the question to make it explicit.Culicid
B
14

You can try something like this:

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

and you can obviously get more thread characteristic if you need.

Breunig answered 16/5, 2016 at 19:49 Comment(0)
T
14

Apache Commons users can use ThreadUtils. The current implementation uses the walk the thread group approach previously outlined.

for (Thread t : ThreadUtils.getAllThreads()) {
      System.out.println(t.getName() + ", " + t.isDaemon());
}
Trypanosomiasis answered 11/4, 2018 at 11:25 Comment(0)
C
11

To get a list of threads and their full states using the terminal, you can use the command below:

jstack -l <PID>

Which <PID> is the id of process running on your computer. To get the process id of your java process you can simply run the jps command.

Also, you can analyze your thread dump that produced by jstack in TDAs (Thread Dump Analyzer) such fastthread or spotify thread analyzer tool.

Colburn answered 5/7, 2019 at 15:55 Comment(0)
M
6

Code snippet to get list of threads started by main thread:

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();
        }
    }
}

output:

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 you need all threads including system threads, which have not been started by your program, remove below condition.

if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())

Now output:

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
Muster answered 30/7, 2016 at 15:19 Comment(0)
A
5

In Groovy you can call private methods

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

In Java, you can invoke that method using reflection provided that security manager allows it.

Actinology answered 12/7, 2013 at 10:17 Comment(1)
I get error, getThreads not defined for Thread. And I dont see this function in the documentation.Undamped
A
4

In the java console, hit Ctrl-Break. It will list all threads plus some information about the heap. This won't give you access to the objects of course. But it can be very helpful for debugging anyway.

Antonelli answered 24/8, 2009 at 16:53 Comment(0)
P
3
    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 + "  ");
        }
    }
Pessimist answered 24/8, 2009 at 17:15 Comment(0)
S
1

You can use getAllThreadIds that Returns all live thread IDs. Some threads included in the returned array may have been terminated when this method returns.

ManagementFactory.getThreadMXBean().getAllThreadIds()
Subdiaconate answered 18/12, 2015 at 11:38 Comment(2)
You should give more context around you answer to be useful to not only who asked the question, but also anyone else stumbling on the answer.Upshot
This gives the thread ids and not instances of the thread class, which is what this question is asking.Phyllotaxis

© 2022 - 2024 — McMap. All rights reserved.