为何100万个Virtual Thread未输出100万条结果?
虚拟线程(Virtual Thread)输出不完整问题解析
你的代码如下:
List<Thread> threads = new ArrayList<>(); for(int i = 0; i < 1_000_000; i++){ var thread = Thread.ofVirtual() .unstarted(() -> { String n = Thread.currentThread().toString(); System.out.println(n); }); threads.add(thread); } for (var thread: threads){ thread.start(); }
问题原因
主线程启动所有虚拟线程后,没有等待它们执行完毕就直接退出了。Java虚拟机的规则是:当所有非守护线程运行结束时,JVM会立即终止进程,不管其他线程(包括虚拟线程)是否执行完成。大部分虚拟线程还没来得及执行到System.out.println语句,就被JVM强制终止,所以输出条数远少于预期的100万条。
解决方案
用CountDownLatch让主线程等待所有虚拟线程执行完成,修改后的代码如下:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; public class VirtualThreadTest { public static void main(String[] args) throws InterruptedException { int totalThreads = 1_000_000; CountDownLatch latch = new CountDownLatch(totalThreads); List<Thread> threads = new ArrayList<>(); for(int i = 0; i < totalThreads; i++){ var thread = Thread.ofVirtual() .unstarted(() -> { try { String n = Thread.currentThread().toString(); System.out.println(n); } finally { latch.countDown(); // 确保即使抛出异常也会递减计数器 } }); threads.add(thread); } for (var thread: threads){ thread.start(); } latch.await(); // 主线程阻塞,直到所有虚拟线程执行完成 } }
补充说明
CountDownLatch初始化时设置为虚拟线程总数,每个虚拟线程执行完逻辑后(包括异常场景)都会调用countDown(),计数器减1- 主线程调用
latch.await()会一直阻塞,直到计数器变为0,也就是所有虚拟线程都执行完毕,才会继续执行并退出JVM - 注意:100万条控制台输出会占用大量IO资源,实际运行时可能速度极慢,建议改为统计执行完成的线程数量,或者采用批量输出的方式优化性能
内容的提问来源于stack exchange,提问作者Mark Rensen
相关产品推荐
相关产品推荐

