Understanding Java Virtual Threads and Their Use in Spring Boot
This article explains Java 21's virtual threads, their lightweight and high‑concurrency advantages, demonstrates basic creation and Spring Boot integration, compares performance against traditional threads, and offers additional Java performance optimization techniques.
Virtual threads, introduced in Java 21, are a lightweight concurrency feature managed by the JVM, offering lower memory usage and higher scalability compared to traditional OS threads.
Lightweight : Managed by JVM, low memory and creation cost, allowing hundreds of thousands of threads.
High concurrency : Ideal for I/O‑bound workloads and responsive applications.
Automatic management : No manual thread‑pool handling; the JVM schedules threads automatically.
Basic Usage
Creating and starting a virtual thread is straightforward:
Thread virtualThread = Thread.ofVirtual().start(() -> {
System.out.println("虚拟线程正在运行");
});
System.out.println("主线程正在运行");Virtual threads can also be created in an unstarted state and started later:
Thread virtualThread = Thread.ofVirtual()
.name("虚拟线程")
.unstarted(() -> System.out.println("虚拟线程运行中"));
virtualThread.start();
virtualThread.join(); // wait for completionUsing Virtual Threads in Spring Boot
To enable virtual threads in a Spring Boot project, use Java 21 or newer 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>Expose actuator endpoints in application.properties and configure Tomcat to use a virtual‑thread executor:
management.endpoints.web.exposure.include=health,info,metrics @Bean
public TomcatProtocolHandlerCustomizer
protocolHandlerVirtualThreadExecutorCustomizer() {
return protocolHandler -> protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
}Experiment: Traditional Threads vs Virtual Threads
1. Creating 100,000 threads
Traditional threads took about 18.6 seconds, while virtual threads completed in 3.7 seconds, a ~500 % speedup.
for (int i = 0; i < 100_000; i++) {
Thread thread = Thread.ofVirtual().unstarted(() -> System.out.println(i));
thread.start();
thread.join();
}2. HTTP request performance
In a test of 1,600 requests with 400 concurrent users, virtual threads reduced total time from 9.659 s to 7.912 s and increased throughput from 165.65 rps to 202.22 rps.
Other Java Performance Tips
Use parallel streams for CPU‑bound tasks.
Leverage CompletableFuture for asynchronous I/O.
Optimize database access with caching.
Employ object pools (e.g., Apache Commons Pool) to reduce allocation overhead.
Conclusion
Virtual threads simplify concurrency, enable massive thread counts, and significantly improve performance in high‑concurrency Spring Boot applications, while additional techniques such as parallel streams, CompletableFuture, caching, and object pooling further boost Java application efficiency.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
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.