为什么不在 ForkJoinPool 中使用虚拟线程?
刚才看到一张帖子提到为什么在 ForkJoinPool 中不使用虚拟线程?
在 JDK 21 中进行测试
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
System.out.println("Running : " + Thread.currentThread());
};
/* 虚拟线程默认没有名字*/
Thread thread = Thread.ofVirtual().name("VT").start(task);
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
forkJoinPool.execute(task);
Thread.sleep(1000);
}
发现 ForkJoinPool 的任务是在平台线程 (platform thread) 中执行的,但是虚拟线程中的任务是在 ForkJoinPool 中实现的,难道虚拟线程可以替代池化吗?
平台线程由操作系统调度,创建和销毁慢,资源消耗较高,每次线程的上下文切换涉及到内核态线程的上下文切换。而虚拟线程是基于平台线程实现的,可创建数百万线程,由 JVM 调度,创建和销毁快,资源消耗较低,不涉及操作系统层面的上下文切换。
ForkJoinPool 常用来做并行计算,及并行流parallel stream
的底层实现。
为什么不在 ForkJoinPool 中使用虚拟线程?
- ForkJoinPool 适用于 CPU 密集型任务,虚拟线程适用于 IO 密集型任务
- CPU 密集型任务不需要大量超过 CPU 个数的线程,这对于大量的计算并没有很大的提升
- 虚拟线程创建和销毁较廉价,且资源消耗低,一般任务执行完就销毁,没必要池化 (pool)
参考资料:
https://www.reddit.com/r/java/comments/1i3owiv/why_are_virtualthreads_not_used_in_the_common/
https://berksoftware.com/24/1/When-Not-To-Use-Virtual-Threads
https://openjdk.org/jeps/425
https://popcornylu.gitbooks.io/java_multithread/content/threadpool/forkjoin.html