使用虚拟线程工厂时Java应用程序立即退出的问题
为什么使用虚拟线程工厂的ScheduledExecutorService会让程序立即退出?
先看你写的代码:
public static void main(String[] args){ ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(Thread.ofVirtual().factory()); executor.scheduleWithFixedDelay(() -> System.out.println("A"), 0, 1000, TimeUnit.MILLISECONDS); executor.scheduleWithFixedDelay(() -> System.out.println("B"), 0, 1, TimeUnit.MINUTES); }
运行这段代码时程序会立刻以退出码0结束,但换成Executors.newSingleThreadScheduledExecutor()(不指定虚拟线程工厂),程序就会一直运行,调度任务能正常执行。
核心原因:JVM对线程的退出判定逻辑差异
- 普通平台线程版本:默认的
newSingleThreadScheduledExecutor()会创建一个非守护的平台线程作为调度器的核心工作线程。JVM的退出规则是:必须等所有非守护平台线程都终止,才会停止运行。当main线程执行完代码结束后,这个调度线程还在后台持续运行,所以JVM不会退出,任务能按计划执行。 - 虚拟线程版本:用
Thread.ofVirtual().factory()创建的是虚拟线程作为调度线程。JVM判定是否退出时,只看非守护平台线程的状态,虚拟线程的运行状态不影响JVM退出。main线程是平台线程,它执行完代码后立刻终止,此时JVM中没有其他非守护平台线程在运行,所以直接退出,虚拟调度线程还没来得及执行任务就被终止,程序自然立刻结束。
解决办法
如果想让使用虚拟线程的调度器保持程序运行,只要让main线程不立刻终止即可,比如让它等待调度器的终止信号:
public static void main(String[] args) throws InterruptedException { ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(Thread.ofVirtual().factory()); executor.scheduleWithFixedDelay(() -> System.out.println("A"), 0, 1000, TimeUnit.MILLISECONDS); executor.scheduleWithFixedDelay(() -> System.out.println("B"), 0, 1, TimeUnit.MINUTES); // 让main线程一直等待,直到调度器被关闭 executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); }
内容的提问来源于stack exchange,提问作者KunLun
相关产品推荐
相关产品推荐

