首先需要明白虚拟线程解决了什么问题: 减少内核线程切换的开销

示例代码:

import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class Main {
    static int minThreadCnt = Integer.MAX_VALUE;
    static int maxThreadCnt = Integer.MIN_VALUE;
    public static void main(String[] args) {
        
        // 记录系统线程数
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
            ThreadInfo[] threadInfo = threadBean.dumpAllThreads(false, false);
            synchronized (Main.class) {
                minThreadCnt = Math.min(minThreadCnt, threadInfo.length);
            }
            synchronized (Main.class) {
                maxThreadCnt = Math.max(maxThreadCnt, threadInfo.length);
            }
        }, 1, 1, TimeUnit.SECONDS);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long l = System.currentTimeMillis();
        try (var executor = Executors.newCachedThreadPool()
            // var executor = Executors.newFixedThreadPool(100)
            // var executor = Executors.newCachedThreadPool()
            ) {
            IntStream.range(0, 10000).forEach(i -> {
                executor.submit(() -> {
                    // double ret = 0;
                    // for(int j = 0; j < 10000000; j++) {
                    //     ret += Math.sqrt(j);
                    // }
                    // return ret;
                    File file = new File("D:\\temp_cur\\" + i + ".txt");
                    try {
                        while(!file.createNewFile());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            });
        }
        System.out.printf("cost: %d ms, min thread count: %d, max thread count: %d\n", System.currentTimeMillis() - l, minThreadCnt, maxThreadCnt);
        scheduledExecutorService.close();
    }
}

在示例代码中进行了两种操作,一个是 Math.sqrt() 一种计算密集型的操作,一种是创建文件,一个 io 型的操作。和三种线程池,一种是虚拟线程,一种是固定线程数量的线程池,一种是利用缓存线程的线程池(按需创建)。

从结果中可以很明显的发现(运行时需要 jvm 参数 --enable-preview),虚拟线程在 io 型的操作中执行时间较短,而在计算密集型的操作上区别不大。