Backend Development 7 min read

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.

Architecture Digest
Architecture Digest
Architecture Digest
Understanding Java Virtual Threads and Their Use in Spring Boot

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 completion

Using 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.

JavaperformanceconcurrencySpring BootVirtual ThreadsJava 21
Architecture Digest
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.