JDK21虚拟线程(jdk21虚拟线程pinned)

很久没有发贴了,最近在做大量数据处理的项目,是一种IO密集型项目。一般我们是采用的普通多线程的方式进行处理,效率感觉也不是很快。cpu好像也到了极限,内存也不是占用很大。【这里面其实还有一个问题就是我们的CPU其实很大有96核心,同事表示貌似没有吃透这块原理,他没想着去调大我们的核心线程池大小,而是去在一个服务器上部署了多个节点,这种我认为是有问题的,感觉这是跟k8s部署多节点有混淆的意思。】,以下是我基于简单的创建虚拟线程和解决上面【】里面事情做的记录。

直接上虚拟线程:

package com.game.game21.virtual;

public class VirtualThread {

    public static void main(String[] args) throws InterruptedException {
        var t=Thread.ofVirtual().start(() -> {
            System.out.println("Virtual Thread");
        });

      /*  var executors = Executors.newVirtualThreadPerTaskExecutor();
        executors.submit(() -> {
            //异步任务,这里的参数不用lambda表达式的话要传一个实现Runnable的类
        });*/
        t.join();
    }
}
package com.game.game21.virtual;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class VirtualThrad3 {

    public static void main(String[] args) throws InterruptedException {
        // 创建一个使用虚拟线程的线程池
        try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
            // 提交1000个任务
            for (int i = 0; i < 1000; i++) {
                final int taskId = i;
                executor.submit(() -> {
                    System.out.println("Task " + taskId + " executed by " + Thread.currentThread());
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return taskId;
                });
            }
        } // 线程池会自动关闭

    }

}


在 Java 21+ 中引入的虚拟线程(Virtual Threads)与传统线程池有一些重要区别,特别是在线程池大小设置方面。

虚拟线程池的特点

  1. 不需要设置线程池大小:虚拟线程的设计初衷就是可以创建大量(数百万)轻量级线程,而不需要像平台线程(传统线程)那样担心资源耗尽问题。
  2. 资源管理方式不同:虚拟线程由 JVM 管理,在底层使用少量的平台线程作为载体线程(carrier threads)。

为什么不需要设置大小

  • 虚拟线程非常轻量(内存开销约几百字节)
  • 阻塞操作不会占用载体线程(当虚拟线程阻塞时,载体线程可以执行其他虚拟线程)
  • JVM 会自动管理载体线程池(通常是CPU核心数大小的ForkJoinPool)

最佳实践

虽然不需要设置虚拟线程池大小,但可以考虑以下方面:

  1. 限制并发任务数量:如果担心资源消耗(如数据库连接),可以使用信号量(Semaphore)限制并发数

java

复制

下载

try (var semaphore = new Semaphore(100)) { // 限制100并发
    List<Future<?>> futures = new ArrayList<>();
    for (int i = 0; i < 10_000; i++) {
        semaphore.acquire();
        futures.add(executor.submit(() -> {
            try {
                // 任务代码
            } finally {
                semaphore.release();
            }
        }));
    }
}
  1. 载体线程池配置:可以通过系统属性调整载体线程池大小(通常不需要)
  2. jdk.virtualThreadScheduler.parallelism - 并行度(默认是CPU核心数)
  3. jdk.virtualThreadScheduler.maxPoolSize - 最大池大小

与传统线程池对比

特性

虚拟线程池

传统线程池

线程开销

极小(几百字节)

较大(约1MB)

阻塞影响

几乎无影响

占用线程

池大小

不需要设置

需要谨慎设置

适用场景

高并发I/O密集型

CPU密集型

总结:使用虚拟线程时,通常不需要也不应该设置线程池大小,这是虚拟线程的主要优势之一。

原文链接:,转发请注明来源!