Boost SpringBoot Performance: Harness Java Virtual Threads for 200× Speedup
This article explains Java virtual threads, compares them with regular threads, shows how to enable them in SpringBoot, and presents performance tests that reveal up to a 200‑fold reduction in latency for IO‑bound workloads.
What Are Virtual Threads
Virtual threads are a feature added in Java 19, similar to Go's goroutines, providing a lightweight threading model that Java developers have long awaited.
Differences Between Virtual and Regular Threads
Virtual threads are "fake" threads managed by the JVM rather than the operating system, allowing a single OS thread to schedule thousands of virtual threads. They consume far less memory, enabling the creation of millions of threads when resources permit.
Using Virtual Threads in SpringBoot
By replacing the default asynchronous thread pool and the HTTP handling thread pool with virtual threads, SpringBoot applications can achieve dramatic performance gains.
Configuration
The Java version used is
java-20.0.2-oracleand SpringBoot version is
3.1.2.
Enable virtual threads with the following configuration:
<code>@Configuration
@ConditionalOnProperty(prefix = "spring", name = "virtual-thread", havingValue = "true")
public class ThreadConfig {
@Bean
public AsyncTaskExecutor applicationTaskExecutor() {
return new TaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor());
}
@Bean
public TomcatProtocolHandlerCustomizer<?> protocolHandlerCustomizer() {
return protocolHandler -> {
protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
};
}
}
</code>@Async Performance Comparison
An asynchronous service that sleeps for 50 ms (simulating I/O) is tested by invoking the method 100 000 times.
<code>@Service
public class AsyncService {
@Async
public void doSomething(CountDownLatch countDownLatch) throws InterruptedException {
Thread.sleep(50);
countDownLatch.countDown();
}
}
</code> <code>@Test
public void testAsync() throws InterruptedException {
long start = System.currentTimeMillis();
int n = 100000;
CountDownLatch countDownLatch = new CountDownLatch(n);
for (int i = 0; i < n; i++) {
asyncService.doSomething(countDownLatch);
}
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "ms");
}
</code>Results:
Regular threads:
678 seconds(over 10 minutes)
Virtual threads:
3.9 seconds– roughly 200× faster.
HTTP Request Performance Comparison
A simple GET endpoint that sleeps 50 ms is stress‑tested with JMeter (500 concurrent threads, 10 000 requests).
<code>@RequestMapping("/get")
public Object get() throws Exception {
Thread.sleep(50);
return "ok";
}
</code>Results for regular threads show median and 90/95/99 percentiles exceeding 150 ms because OS threads are scarce and block while waiting.
Virtual threads keep the maximum response time below 100 ms, demonstrating far better resource utilization.
Conclusion
Virtual threads provide a clear performance advantage for I/O‑bound scenarios, which constitute the majority of typical web applications. They are less beneficial for CPU‑bound workloads. Leveraging them in SpringBoot can dramatically reduce latency and improve scalability.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.