Boost Spring Boot Performance with Java 21 Virtual Threads: A Hands‑On Guide
Learn how to enable and test Java 21 virtual threads in Spring Boot 3.2.5, compare their throughput against platform threads with JMeter, and explore performance limits through sample code and benchmarks, revealing when virtual threads excel and their constraints for CPU‑bound tasks.
1. Introduction
This article explains how to leverage Java 21 virtual threads in a Spring Boot 3.2.5 application to improve throughput.
Virtual Thread vs. Platform Thread
Virtual threads are decoupled from operating‑system threads, making them lightweight. The goal is to demonstrate that creating millions of virtual threads does not cause out‑of‑memory errors, unlike platform threads.
2. Practical Example
2.1 Enable Virtual Thread Support
When using Java 21 with Spring Boot 3.2+, enable virtual threads by setting the property spring.threads.virtual.enabled=true :
<code>spring:
threads:
virtual:
enabled: true</code>After enabling, the application can run on virtual threads, but thorough testing is required.
2.2 Verify Virtual Threads
A simple controller prints the current thread name:
<code>@GetMapping("name")
public String toThread() {
return Thread.currentThread().toString();
}</code>The response shows an instance of VirtualThread , confirming that the request is handled by a virtual thread.
2.3 Performance Comparison
Using JMeter, a load test simulates 1,000 concurrent users calling /load , which sleeps for one second to mimic a blocking operation.
<code>@RestController
@RequestMapping("/load")
public class LoadTestController {
private static final Logger logger = LoggerFactory.getLogger(LoadTestController.class);
@GetMapping
public void test() throws InterruptedException {
logger.info("日志信息...");
Thread.sleep(1000);
}
}</code>The response‑time chart for platform threads peaks around 5,000 ms, indicating thread‑pool saturation.
When the same test runs on virtual threads, the response time stabilizes near 1,000 ms, showing efficient resource usage.
Virtual threads handle the load more smoothly, but the benefit is most noticeable in I/O‑bound scenarios.
CPU‑Intensive Test
A second benchmark calculates a large factorial to create a CPU‑bound workload:
<code>// Compute factorial of a large number
@GetMapping("calc")
public String calc() {
int number = 20000;
long startTime = System.currentTimeMillis();
System.out.println("开始时间: " + new Date(startTime));
factorial(number);
long endTime = System.currentTimeMillis();
System.out.println("结束时间: " + new Date(endTime));
long duration = endTime - startTime;
return "计算" + number + "! 耗时: " + duration + " 毫秒";
}
private static BigInteger factorial(int n) {
BigInteger result = BigInteger.ONE;
for (int i = 1; i <= n; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}</code>Performance results for platform threads and virtual threads are similar, with virtual threads showing slightly smoother execution, confirming that virtual threads do not provide a clear advantage for CPU‑bound tasks.
Conclusion
Virtual threads dramatically improve throughput for I/O‑bound workloads, reducing response times and stabilizing performance. However, for CPU‑intensive operations they offer little benefit and may even be unsuitable. Developers should adopt virtual threads primarily for blocking I/O scenarios.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.