Boost Java Concurrency: How Project Loom’s Virtual Threads Supercharge Spring Boot
This article explains Project Loom’s virtual threads, shows how to enable them in a Spring Boot 3.1 application with Java 20, provides code samples and performance test results that demonstrate dramatically higher throughput under high concurrency.
What is Project Loom?
Project Loom is an Oracle initiative that aims to dramatically reduce the effort required to write, maintain, and observe high‑throughput concurrent applications by introducing lightweight virtual threads managed by the JVM, making a "one‑thread‑per‑request" model practical.
How to Use Virtual Threads
Java Version Selection
Virtual threads are available starting with Java 19. The author uses the Azul Zulu distribution version 20.30.11 on a Mac M1.
Create a Test Project
Generate a Spring Boot project via Spring Initializr or an IDE, add the
spring-webdependency, and use Spring Boot 3.1 with Java 20.
Enable Virtual Thread Support
Virtual thread support is disabled by default in Java 19 and must be enabled via Maven compiler arguments.
<code><plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin></code>Enable virtual threads by configuring a bean
<code>@Bean
TomcatProtocolHandlerCustomizer<?> threadExecutorCustomizer() {
return protocolHandler -> protocolHandler.setExecutor(
Executors.newVirtualThreadPerTaskExecutor());
}
</code>The bean customizes Tomcat’s protocol handler to use an executor that creates a virtual thread for each task, allowing massive concurrency with minimal overhead.
Add a Test Endpoint
<code>@Slf4j
@RequestMapping
@RestController
public class DemoController {
@GetMapping("/")
public String demo() {
try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { log.error(e.getMessage()); }
return "Current Thread Name: " + Thread.currentThread();
}
}
</code>Calling
Thread.currentThread()lets you verify that the request is handled by a virtual thread.
Performance Test Comparison
100‑Thread Test
Without virtual threads
Throughput: 300 req/s
With virtual threads
Throughput: 300 req/s
300‑Thread Test
Without virtual threads
Throughput: 650 req/s
With virtual threads
Throughput: 950 req/s
500‑Thread Test
Without virtual threads
Throughput: 650 req/s
With virtual threads
Throughput: 1500 req/s
Summary
Virtual threads greatly improve performance for blocking operations, and the benefit becomes more pronounced as the number of concurrent requests increases. The tests were conducted without additional Spring Boot tuning.
References
[1] Azul Zulu Distribution 20.30.11: https://www.azul.com/downloads/?version=java-20-sts&os=macos&architecture=arm-64-bit&package=jdk#zulu
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.