随着 Java 21 的发布,虚拟线程(Virtual Threads)成为了正式特性,彻底改变了 Java 的并发编程方式。它们为传统线程提供了更轻量、更易扩展的替代方案,让开发者能够编写出更加简洁高效的并发代码。
虚拟线程
虚拟线程为异步 Java 开发带来了革命性的变化。它们让 JVM 拥有了类似 Go 的并发能力,使高吞吐量应用的代码结构更加简洁、易于维护。如果你正在开发 Web 服务、文件处理器或任何 I/O 密集型应用,虚拟线程会成为你的得力助手。
虚拟线程是由 Java 虚拟机(JVM)直接管理的轻量级线程,而不是由操作系统管理。与平台线程(也称为内核线程或本地线程)相比,平台线程的创建和管理成本较高,而虚拟线程则极为廉价,可以轻松支持成千上万甚至上百万的并发线程。
虚拟线程依然基于熟悉的 java.lang.Thread
API,这意味着你无需学习新的并发模型或库。
传统线程与操作系统线程是一一对应的:
- 每个 Java 线程对应一个操作系统线程
- 阻塞线程(如 I/O 操作)会占用操作系统资源
而虚拟线程采用多对一模型,允许大量虚拟线程共享少量操作系统线程。当虚拟线程遇到阻塞操作(如 sleep()
或 read()
)时,JVM 会自动挂起该线程,让底层的承载线程去执行其他任务。
虚拟线程项目示例
下面的代码演示了如何配置 Tomcat(Spring Boot 默认的 Web 服务器)使用虚拟线程来处理请求任务,替代传统的平台线程。
@SpringBoojtApplication
@Configuration
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
return protocolHandler -> {
protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
};
}
}
创建生成二维码的接口:
@RestController
@RequestMapping(path = "/api/qr")
public class QrController {
private final QRCodeWriter qrWriter = new QRCodeWriter();
private final Map<String, byte[]> store = new ConcurrentHashMap<>();
@GetMapping("/generate")
public ResponseEntity<String> generate(@RequestParam("text") String text,
@RequestParam(value = "size", defaultValue = "250") int size) {