Java
Thread Management
Programming
Coding Tips
Software Development

Get a list of all threads currently running in Java

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If you want a list of all live threads inside a Java process, the easiest in-process API is usually Thread.getAllStackTraces(). If you need richer monitoring details such as blocked time, thread IDs, or deadlock detection, use ThreadMXBean from java.lang.management.

These APIs answer slightly different questions. One is the fastest way to enumerate live Thread objects. The other is the better tool for diagnostics and monitoring.

The Simplest Programmatic Option

Thread.getAllStackTraces() returns a map from each live Thread to its current stack trace. Even if you do not care about the stack frames, the map keys already give you the active threads.

java
1import java.util.Map;
2
3public class ListThreads {
4    public static void main(String[] args) {
5        Map<Thread, StackTraceElement[]> threads = Thread.getAllStackTraces();
6
7        for (Thread thread : threads.keySet()) {
8            System.out.println(
9                thread.getName() +
10                " | id=" + thread.getId() +
11                " | state=" + thread.getState() +
12                " | daemon=" + thread.isDaemon()
13            );
14        }
15    }
16}

This is often enough for lightweight diagnostics, debugging endpoints, or internal support tooling.

Why This Works

Every live thread has a current stack, so the JVM can snapshot all threads by collecting stack traces. That is why this API gives you more than just names: it can also show what each thread is doing.

java
1for (Map.Entry<Thread, StackTraceElement[]> entry : Thread.getAllStackTraces().entrySet()) {
2    System.out.println("Thread: " + entry.getKey().getName());
3    for (StackTraceElement frame : entry.getValue()) {
4        System.out.println("  at " + frame);
5    }
6}

This becomes useful when an application appears hung, blocked, or unexpectedly busy.

Use ThreadMXBean for Richer Monitoring

If you want more management-oriented data, the management API is better.

java
1import java.lang.management.ManagementFactory;
2import java.lang.management.ThreadInfo;
3import java.lang.management.ThreadMXBean;
4
5public class ThreadMxBeanDemo {
6    public static void main(String[] args) {
7        ThreadMXBean bean = ManagementFactory.getThreadMXBean();
8        long[] ids = bean.getAllThreadIds();
9        ThreadInfo[] infos = bean.getThreadInfo(ids, 20);
10
11        for (ThreadInfo info : infos) {
12            if (info != null) {
13                System.out.println(
14                    info.getThreadName() +
15                    " | id=" + info.getThreadId() +
16                    " | state=" + info.getThreadState()
17                );
18            }
19        }
20    }
21}

This API is better suited for things like:

  • deadlock analysis
  • blocked and waited counts
  • CPU time reporting where supported
  • deeper management tooling

ThreadGroup Exists, but It Is Usually Not the Best Answer

Older Java examples sometimes walk the root ThreadGroup and enumerate from there. That can work, but it is usually more awkward and less attractive than the APIs above.

For most modern code:

  • use Thread.getAllStackTraces() for a simple thread list
  • use ThreadMXBean for richer thread diagnostics

There is usually no reason to start with ThreadGroup unless you are maintaining legacy code that already depends on it.

Programmatic Listing Versus External Tools

Sometimes the best answer is not code at all. For a live JVM, external tools are often better for one-off debugging:

  • 'jstack'
  • 'jcmd'
  • Java Flight Recorder
  • profiler or IDE thread-dump tools

Programmatic enumeration is most useful when the information must be exposed inside the application itself, such as through an admin endpoint or support diagnostic screen.

Treat the Result as a Snapshot

This is easy to forget. The list you get is a moment-in-time snapshot, not a permanently stable set of threads. Threads may start or stop immediately after you collect the data.

That means thread enumeration is good for diagnostics, but it should not be treated like a transactional inventory of JVM state.

Common Pitfalls

The biggest mistake is assuming the thread list stays stable while the program keeps running. Another is using ThreadGroup by default just because older examples do. Developers also sometimes collect full stack traces too aggressively in production, which can become noisy or expensive if done too frequently. Finally, if your goal is one-time debugging of a live process, writing code for thread enumeration may be more work than using jstack or jcmd directly.

Summary

  • 'Thread.getAllStackTraces() is the easiest in-process way to list live threads.'
  • 'ThreadMXBean is better when you need richer thread-management details.'
  • 'ThreadGroup is usually a legacy-style approach rather than the best modern starting point.'
  • External tools are often better for one-off live debugging.
  • Treat any programmatic thread list as a snapshot, not a permanently fixed view of the JVM.

Course illustration
Course illustration

All Rights Reserved.