Skip to content

ThreadUtil - 线程工具类

ThreadUtil 提供线程相关的工具方法,主要用于创建虚拟线程工厂。

核心特性

  • 虚拟线程支持:自动检测并创建虚拟线程(Java 21+)
  • 优雅降级:不支持虚拟线程时自动使用普通线程
  • 零依赖:纯反射实现,无需额外依赖
  • 线程安全:所有方法都是线程安全的

Maven 依赖

xml
<dependency>
    <groupId>com.molandev</groupId>
    <artifactId>molandev-util</artifactId>
</dependency>

API 说明

createVirtualThreadFactory()

创建线程工厂,优先使用虚拟线程。

方法签名:

java
public static ThreadFactory createVirtualThreadFactory()

返回值:

  • Java 21+:返回虚拟线程工厂
  • Java 8-17:返回默认线程工厂

实现原理:

java
public class ThreadUtil {
    public static ThreadFactory createVirtualThreadFactory() {
        try {
            // 通过反射创建虚拟线程工厂(Java 21+)
            Class<?> threadClass = Class.forName("java.lang.Thread");
            java.lang.reflect.Method ofVirtualMethod = threadClass.getDeclaredMethod("ofVirtual");
            Object builder = ofVirtualMethod.invoke(null);
            
            Class<?> builderClass = builder.getClass();
            java.lang.reflect.Method nameMethod = builderClass.getDeclaredMethod("name", String.class, long.class);
            Object namedBuilder = nameMethod.invoke(builder, "virtual-", 0L);
            
            java.lang.reflect.Method factoryMethod = builderClass.getDeclaredMethod("factory");
            return (ThreadFactory) factoryMethod.invoke(namedBuilder);
        } catch (Exception e) {
            // 不支持虚拟线程,返回默认线程工厂
            return Executors.defaultThreadFactory();
        }
    }
}

使用示例

基本用法

java
import com.molandev.framework.util.ThreadUtil;
import java.util.concurrent.*;

// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    10,                                    // 核心线程数
    20,                                    // 最大线程数
    60L, TimeUnit.SECONDS,                 // 空闲存活时间
    new LinkedBlockingQueue<>(100),        // 任务队列
    ThreadUtil.createVirtualThreadFactory() // 使用虚拟线程工厂
);

// 提交任务
executor.execute(() -> {
    System.out.println("Task running in: " + Thread.currentThread());
});

Spring 线程池配置

java
import com.molandev.framework.util.ThreadUtil;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    
    // 使用虚拟线程工厂
    executor.setThreadFactory(ThreadUtil.createVirtualThreadFactory());
    
    executor.setCorePoolSize(10);
    executor.setMaxPoolSize(20);
    executor.setQueueCapacity(100);
    executor.setThreadNamePrefix("async-task-");
    executor.initialize();
    
    return executor;
}

定时任务线程池

java
import com.molandev.framework.util.ThreadUtil;
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
import java.util.concurrent.*;

@Bean
public TaskScheduler taskScheduler() {
    ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(
        10,
        ThreadUtil.createVirtualThreadFactory()
    );
    
    return new ConcurrentTaskScheduler(scheduler);
}

虚拟线程优势

为什么使用虚拟线程?

虚拟线程(Virtual Threads)是 Java 21 引入的轻量级线程:

传统线程(Platform Thread):

  • 每个线程占用 ~1MB 栈内存
  • 创建和销毁成本高
  • 系统线程数有限(通常几千个)

虚拟线程(Virtual Thread):

  • 每个线程只占用几 KB 内存
  • 创建和销毁成本极低
  • 可以轻松创建百万级线程

适用场景

适合使用虚拟线程的场景:

  • I/O 密集型任务(网络请求、数据库查询)
  • 高并发场景(大量并发请求)
  • 异步事件处理
  • 定时任务调度

不适合虚拟线程的场景:

  • CPU 密集型计算
  • 同步块较多的代码(可能阻塞载体线程)

实际应用

1. 事件驱动模块

java
@Bean(name = "eventExecutor")
public ThreadPoolTaskExecutor eventExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setThreadFactory(ThreadUtil.createVirtualThreadFactory());
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(20);
    executor.setQueueCapacity(100);
    executor.initialize();
    return executor;
}

2. 异步任务处理

java
@Bean
public Executor asyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setThreadFactory(ThreadUtil.createVirtualThreadFactory());
    executor.setThreadNamePrefix("async-");
    executor.initialize();
    return executor;
}

@Async("asyncExecutor")
public void processAsync() {
    // 异步处理逻辑
}

3. 定时任务调度

java
@Bean
public TaskScheduler taskScheduler() {
    ThreadFactory threadFactory = ThreadUtil.createVirtualThreadFactory();
    
    ScheduledThreadPoolExecutor scheduler = 
        new ScheduledThreadPoolExecutor(10, threadFactory);
        
    return new ConcurrentTaskScheduler(scheduler);
}

性能对比

指标普通线程虚拟线程
内存占用~1MB/线程~1KB/线程
创建速度较慢极快
上下文切换较慢快速
最大并发数数千数百万
适用场景CPU密集I/O密集

注意事项

1. 自动降级

ThreadUtil 在不支持虚拟线程的环境下会自动降级到普通线程,业务代码无需修改:

java
// 这段代码在任何 Java 版本都能正常运行
ThreadFactory factory = ThreadUtil.createVirtualThreadFactory();
// Java 21+: 虚拟线程
// Java 8-17: 普通线程

2. 无需版本判断

与旧的实现不同,现在无需手动判断 Java 版本:

java
// ❌ 旧方式(已废弃)
if (JavaVersionUtils.isVirtualThreadsSupported()) {
    factory = createVirtualThreadFactory();
} else {
    factory = Executors.defaultThreadFactory();
}

// ✅ 新方式(推荐)
ThreadFactory factory = ThreadUtil.createVirtualThreadFactory();

3. 线程命名

虚拟线程会自动命名为 virtual-0, virtual-1 等,便于调试:

java
// 虚拟线程输出示例
Thread: VirtualThread[#21,virtual-0]/runnable@ForkJoinPool-1-worker-1

相关工具

常见问题

Q1: 如何确认是否使用了虚拟线程?

A: 可以通过日志或线程名称判断:

java
Thread thread = Thread.currentThread();
System.out.println(thread); 
// 虚拟线程: VirtualThread[#21,virtual-0]
// 普通线程: Thread[pool-1-thread-1,5,main]

Q2: 虚拟线程是否完全替代普通线程?

A: 不是。虚拟线程适合 I/O 密集型任务,CPU 密集型任务仍推荐使用普通线程池。

Q3: 能否在 Java 8 使用?

A: 可以。ThreadUtil 会自动降级到普通线程,保证兼容性。

Q4: 性能提升有多少?

A: 对于 I/O 密集型场景,虚拟线程可以支持 10-100 倍的并发量,但具体提升取决于业务特点。

参考资料