Backend Development 6 min read

Introducing Java 21 Virtual Threads: Basics, Spring Boot Integration, and Performance Comparison

This article explains Java 21 virtual threads, demonstrates how to create and use them in plain Java and Spring Boot, compares their performance against traditional threads in large‑scale and HTTP workloads, and offers additional Java performance optimization tips.

Java Captain
Java Captain
Java Captain
Introducing Java 21 Virtual Threads: Basics, Spring Boot Integration, and Performance Comparison

Virtual threads, introduced in Java 21, are a lightweight alternative to OS threads, offering lower memory usage, high concurrency, and automatic management.

Basic Usage of Virtual Threads

Creating a virtual thread is straightforward; the example below shows how to start a virtual thread and print messages from both the virtual and main threads.

Thread virtualThread = Thread.ofVirtual().start(() -> {
    System.out.println("虚拟线程正在运行");
});
System.out.println("主线程正在运行");

Virtual threads can also be created in a delayed‑start fashion:

Thread virtualThread = Thread.ofVirtual()
    .name("虚拟线程")
    .unstarted(() -> System.out.println("虚拟线程运行中"));
virtualThread.start();
virtualThread.join(); // 等待虚拟线程完成

Using Virtual Threads in Spring Boot

To enable virtual threads in a Spring Boot project, ensure Java 21+, enable preview features in pom.xml , configure performance monitoring, and set up a virtual‑thread executor for Tomcat.

org.apache.maven.plugins
maven-compiler-plugin
21
21
--enable-preview
@Bean
public TomcatProtocolHandlerCustomizer
protocolHandlerVirtualThreadExecutorCustomizer() {
    return protocolHandler -> protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
}

Experiment: Traditional Threads vs Virtual Threads

1. Creating 100,000 Threads

Traditional threads take about 18.6 seconds, while virtual threads complete in roughly 3.7 seconds, a performance gain of nearly 500%.

for (int i = 0; i < 100_000; i++) {
    Thread thread = new Thread(() -> System.out.println(i));
    thread.start();
    thread.join();
}
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 HTTP requests with 400 concurrent connections, traditional threads took 9.659 seconds (165.65 req/s) whereas virtual threads took 7.912 seconds (202.22 req/s), showing higher throughput and lower latency.

Other Java Performance Tips

Additional techniques include using parallel streams, CompletableFuture for asynchronous I/O, optimizing database queries with caching, and employing object pools such as Apache Commons Pool.

List
numbers = Arrays.asList(1,2,3,4,5);
numbers.parallelStream().forEach(number -> {
    System.out.println(number * 2);
});
CompletableFuture
future = CompletableFuture.runAsync(() -> {
    // 异步执行任务
    System.out.println("异步任务完成");
});
future.join(); // 等待任务完成

Conclusion

Virtual threads simplify concurrency, enable massive thread counts, and improve performance in high‑concurrency Spring Boot applications; combined with other optimizations they further boost Java application efficiency.

JavaperformanceconcurrencySpring BootVirtual ThreadsJava 21
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

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.