从虚拟线程调用 System.out.println 时的奇怪行为

问题描述 投票:0回答:1

当运行一个从 java 的新虚拟线程调用 System.out.println 方法的示例程序时,我得到了一些奇怪的结果。这是示例程序:

import java.math.BigInteger;
import java.time.LocalDateTime;

public class VirtualThreadTest {

    public static void main(String[] args) {
        for(int i = 1; i <= 200; i+=1) {
            Thread.ofVirtual().start(() -> {
                System.out.println(LocalDateTime.now());
                System.out.flush();
                expensiveTask();
            });
        }

        sleepMainThread();
    }

    private static void expensiveTask() {
        var bi = BigInteger.ONE;
        for(int i = 2; i < 50_000; i+=1) {
            bi = bi.multiply(BigInteger.valueOf(i));
        }
    }

    private static void sleepMainThread() {
        try {
            Thread.sleep(60_000);
        } catch(Exception e) { e.printStackTrace(); }
    }
}

首先程序会按升序打印当前时间,但过了一会儿它会打印过去的值,例如:

2024-05-08T14:17:34.925188363
2024-05-08T14:17:34.925920200
2024-05-08T14:17:34.925993640
2024-05-08T14:17:34.926365126
...
2024-05-08T14:17:50.927143298
2024-05-08T14:17:51.136285346
2024-05-08T14:17:34.925684196  // prints value in the past
2024-05-08T14:17:51.251390867
2024-05-08T14:17:51.309471812

有人知道为什么会发生这种情况吗?谢谢。

java concurrency jvm java-time virtual-threads
1个回答
0
投票

启动了很多虚拟线程,但有些虚拟线程并没有立即被真实线程发挥。你可以看到它的时间晚于当时最后一个虚拟线程,播放正常。

您可能会看到饥饿,即稍后的虚拟线程首先获得线程。我怀疑与可用的实际物理线程数量有关。

© www.soinside.com 2019 - 2024. All rights reserved.