Java 21 Virtual Threads: Basics, Spring Boot Integration, and Performance Comparison
This article introduces Java 21 virtual threads, explains their lightweight and automatically managed nature, demonstrates basic creation and Spring Boot configuration, and presents performance experiments comparing traditional and virtual threads in both CPU‑bound and HTTP request scenarios.
Virtual threads are a new feature introduced in Java 21 that simplify concurrent programming by providing a lightweight, JVM‑managed alternative to traditional operating‑system threads, enabling the creation of hundreds of thousands of threads with low memory overhead.
Basic Usage of Virtual Threads
Creating a virtual thread is straightforward; you can start it directly or create it in an unstarted state and launch it later.
Thread virtualThread = Thread.ofVirtual().start(() -> {
System.out.println("Virtual thread is running");
});
System.out.println("Main thread is running");Virtual threads also support delayed start and naming:
Thread virtualThread = Thread.ofVirtual()
.name("VirtualThread")
.unstarted(() -> System.out.println("Virtual thread running"));
virtualThread.start();
virtualThread.join(); // wait for completionUsing Virtual Threads in Spring Boot
To use virtual threads in a Spring Boot project, ensure the Java version is 21 or higher and enable preview features in pom.xml :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>21</source>
<target>21</target>
<compilerArgs>
<arg>--enable-preview</arg>
</compilerArgs>
</configuration>
</plugin>Enable performance monitoring in application.properties :
management.endpoints.web.exposure.include=health,info,metricsConfigure Tomcat to use a virtual‑thread executor:
@Bean
public TomcatProtocolHandlerCustomizer
protocolHandlerVirtualThreadExecutorCustomizer() {
return protocolHandler -> protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
}Experiment: Traditional Threads vs. Virtual Threads
1. Creating 100,000 Threads
Traditional threads:
for (int i = 0; i < 100_000; i++) {
Thread thread = new Thread(() -> System.out.println(i));
thread.start();
thread.join();
}Execution time ≈ 18.6 seconds.
Virtual threads:
for (int i = 0; i < 100_000; i++) {
Thread thread = Thread.ofVirtual().unstarted(() -> System.out.println(i));
thread.start();
thread.join();
}Execution time ≈ 3.7 seconds, a performance gain of nearly 500 %.
2. HTTP Request Performance
In a high‑concurrency scenario (1,600 HTTP requests with 400 concurrent threads), the following results were observed:
Traditional threads: 9.659 seconds, 165.65 requests/second.
Virtual threads: 7.912 seconds, 202.22 requests/second.
Virtual threads significantly improve throughput and reduce response time.
Other Java Performance Techniques
Parallel Streams : Use parallelStream() for CPU‑intensive tasks to leverage multiple cores. List numbers = Arrays.asList(1, 2, 3, 4, 5); numbers.parallelStream().forEach(number -> { System.out.println(number * 2); });
Asynchronous Programming with CompletableFuture : Suitable for I/O‑bound tasks. CompletableFuture future = CompletableFuture.runAsync(() -> { // asynchronous task System.out.println("Async task completed"); }); future.join(); // wait for completion
Database Query Optimization : Reduce query count and use caching (e.g., Redis) to minimize I/O.
Memory Management : Employ object pools such as Apache Commons Pool to reuse resources and lower garbage‑collection overhead.
Conclusion
Virtual threads revolutionize Java concurrency by simplifying thread management and boosting performance in high‑load scenarios.
Hundreds of thousands of virtual threads can be created without degrading application performance.
Integrating virtual threads into Spring Boot requires only a few configuration steps and yields noticeable speed improvements.
Additional optimizations—parallel streams, CompletableFuture, query caching, and object pooling—further enhance Java application performance.
By applying these techniques, Spring Boot applications can achieve stronger performance and lower latency under heavy concurrency.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.