JDK 21引入的虚拟线程(Virtual Threads)是 Project Loom 的一部分,旨在显著简化并发编程并提高 Java 应用的可扩展性。以下是虚拟线程的主要特点:
1. 概念
虚拟线程是轻量级线程,与传统的操作系统线程不同,它们由 JVM 管理,消耗资源极少,可以支持数百万级别的并发。
2. 优点
- 高并发:虚拟线程消耗更少的内存,可以轻松创建大量线程,解决传统线程的规模化问题。
- 阻塞友好:虚拟线程可以高效地处理阻塞操作(如 I/O),避免线程阻塞导致资源浪费。
- 调试和分析一致性:虚拟线程和传统线程使用相同的 API,开发和调试体验一致。
- 更简单的代码:简化异步编程,无需使用复杂的回调或 Future。
3. 适用场景
- 高并发服务器:Web 服务、微服务。
- 数据处理:数据库访问、文件处理。
- 事件驱动架构:高吞吐事件流处理。
总的来说,JDK 21 的虚拟线程为 Java 并发编程带来了革命性变化,尤其适合需要高并发处理的现代应用。
配置类:
java
/**
* @author Test
* date 2024/11/29 17:52
* description 虚拟线程配置
*/
@Configuration
public class VirtualThreadConfig {
@Bean
public ExecutorService virtualThreadExecutor() {
return Executors.newVirtualThreadPerTaskExecutor();
}
}
代码实现:
java
@Resource
private ExecutorService executorService;
/**
* 异步执行多个任务
* @return
*/
public void test1() {
for (int i = 0; i < 1000; i++) {
int finalI = i;
executorService.submit(() ->{
System.out.println("处理数据:" + finalI + ",线程:" + Thread.currentThread());
try {
Thread.sleep(1000); // 模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
/**
* 同时执行多个任务并返回
* @return
*/
public List<String> test2() {
// 模拟一组数据
List<String> data = List.of("Data1", "Data2", "Data3", "Data4", "Data5", "Data6", "Data7", "Data8", "Data9", "Data10", "Data11", "Data12", "Data13", "Data14", "Data15", "Data16");
try {
// 创建并发任务
List<Callable<String>> tasks = data.stream()
.map(d -> (Callable<String>) () -> processData(d))
.collect(Collectors.toList());
// 使用 invokeAll 执行并发任务,等待所有任务完成
List<Future<String>> futures = executorService.invokeAll(tasks);
// 收集并返回所有任务结果
return futures.stream()
.map(future -> {
try {
// 获取每个任务的结果
return future.get();
} catch (InterruptedException | ExecutionException e) {
// 处理中断
Thread.currentThread().interrupt();
throw new ApiException("虚拟线程数据处理异常");
}
})
.collect(Collectors.toList());
} catch (InterruptedException e) {
// 处理中断
Thread.currentThread().interrupt();
throw new ApiException("虚拟线程数据处理异常");
}
}
// 模拟数据处理方法
private static String processData(String data) {
try {
// 模拟耗时操作,例如 I/O 操作
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Processed: " + data);
return "Processed: " + data;
}