首先需要明白虚拟线程解决了什么问题: 减少内核线程切换的开销
示例代码:
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 型的操作中执行时间较短,而在计算密集型的操作上区别不大。