如何在Java中列出JVM中的所有虚拟线程?
如何列出JVM中的所有虚拟线程?
传统的线程枚举方法(如ThreadMXBean.dumpAllThreads()、ThreadMXBean.getAllThreadIds()、ThreadGroup.enumerate()和Thread.getAllStackTraces())仅能识别平台线程(Platform Thread),虚拟线程不会被这些方法返回——因为它们不属于传统的ThreadGroup体系,也未被MXBean纳入统计范围。以下是几种可行的解决方案:
1. 使用Java 21+ 标准API(推荐)
Java 21正式引入了Thread.getAllThreads()方法,该方法会返回JVM中所有线程,包括虚拟线程和平台线程。你可以通过Thread.isVirtual()方法区分两者:
import java.util.Arrays; public class ListAllThreads { public static void main(String[] args) { // 示例:创建一个虚拟线程 Thread virtualThread = Thread.ofVirtual().start(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); // 获取所有线程并筛选虚拟线程 Thread[] allThreads = Thread.getAllThreads(); System.out.println("JVM中的所有虚拟线程:"); Arrays.stream(allThreads) .filter(Thread::isVirtual) .forEach(t -> System.out.printf("线程ID: %d, 名称: %s%n", t.threadId(), t.getName())); } }
2. Java 19/20 预览版临时方案(不推荐生产环境)
在虚拟线程处于预览阶段的Java 19和20中,没有公开的标准API枚举所有虚拟线程,但可以通过JDK内部APIjdk.internal.vm.VirtualThreads实现注意:内部API可能在未来版本变更,生产环境禁止使用:
import jdk.internal.vm.VirtualThreads; import java.util.List; public class ListVirtualThreadsPreview { public static void main(String[] args) { Thread virtualThread = Thread.ofVirtual().start(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); // 调用内部API获取所有虚拟线程 List<Thread> virtualThreads = VirtualThreads.listVirtualThreads(); System.out.println("JVM中的所有虚拟线程:"); virtualThreads.forEach(t -> System.out.printf("线程ID: %d, 名称: %s%n", t.threadId(), t.getName())); } }
编译运行时需要添加参数允许访问内部API:--add-exports java.base/jdk.internal.vm=ALL-UNNAMED
3. 自定义跟踪虚拟线程(可控场景)
如果仅需要跟踪自己应用创建的虚拟线程,可以维护一个线程集合,在创建虚拟线程时加入,结束时移除:
import java.util.Collections; import java.util.HashSet; import java.util.Set; public class TrackVirtualThreads { private static final Set<Thread> VIRTUAL_THREADS = Collections.synchronizedSet(new HashSet<>()); // 封装虚拟线程创建逻辑,自动跟踪 public static Thread createVirtualThread(Runnable task) { Thread vt = Thread.ofVirtual().start(() -> { try { task.run(); } finally { VIRTUAL_THREADS.remove(vt); } }); VIRTUAL_THREADS.add(vt); return vt; } public static void main(String[] args) { createVirtualThread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); System.out.println("当前跟踪的虚拟线程:"); VIRTUAL_THREADS.forEach(t -> System.out.printf("线程ID: %d, 名称: %s%n", t.threadId(), t.getName())); } }
这种方式不受JVM版本限制,但仅能跟踪自己创建的虚拟线程,无法获取其他类库或框架创建的实例。
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

