Why Java Virtual Threads Outperform Traditional Threads: A SpringBoot Benchmark
This article explains what Java virtual threads are, compares them with ordinary platform threads, shows how to enable them in SpringBoot, and presents performance benchmarks that reveal virtual threads can be up to two hundred times faster for I/O‑bound workloads.
What are Virtual Threads
Virtual threads were introduced in Java 19 and provide a lightweight concurrency model similar to Go's goroutines, allowing millions of threads to be multiplexed onto a few OS threads.
Difference Between Virtual and Platform Threads
Virtual threads are scheduled by the JVM rather than the operating system, so a single OS thread can manage thousands of virtual threads, consuming far less memory and CPU.
Users familiar with Akka will notice the similarity: Akka handles concurrency at the application level, while virtual threads let the JVM handle it more simply.
Using Virtual Threads in SpringBoot
Configure SpringBoot to replace the default async and Tomcat thread pools with virtual threads.
@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());
};
}
}@Async Performance Comparison
Async service that sleeps 50 ms to simulate I/O:
@Service
public class AsyncService {
@Async
public void doSomething(CountDownLatch latch) throws InterruptedException {
Thread.sleep(50);
latch.countDown();
}
}Test that calls the service 100 000 times:
@Test
public void testAsync() throws InterruptedException {
long start = System.currentTimeMillis();
int n = 100000;
CountDownLatch latch = new CountDownLatch(n);
for (int i = 0; i < n; i++) {
asyncService.doSomething(latch);
}
latch.await();
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "ms");
}Results: ordinary threads took about 678 seconds, while virtual threads completed in 3.9 seconds.
HTTP Request Performance Comparison
Simple GET endpoint that sleeps 50 ms:
@RequestMapping("/get")
public Object get() throws Exception {
Thread.sleep(50);
return "ok";
}JMeter test with 500 concurrent threads, 10 000 requests.
Ordinary threads: minimum 50 ms, but median and higher percentiles exceed 150 ms because the Tomcat thread pool (default max 200) becomes saturated.
Virtual threads: maximum response time stays below 100 ms, showing dramatically reduced wait times and better resource utilization.
Conclusion
Virtual threads provide a clear performance advantage for I/O‑bound workloads, reducing latency and increasing throughput. For CPU‑bound tasks the benefit is smaller. Since most web applications are I/O‑intensive, upgrading to a recent JDK to use virtual threads is highly recommended.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
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.
