Backend Development 8 min read

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.

macrozheng
macrozheng
macrozheng
Boost Java Concurrency: How Project Loom’s Virtual Threads Supercharge Spring Boot

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-web

dependency, 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>&lt;plugin&gt;
  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
&lt;/plugin&gt;
&lt;plugin&gt;
  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
  &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
  &lt;configuration&gt;
    &lt;compilerArgs&gt;--enable-preview&lt;/compilerArgs&gt;
  &lt;/configuration&gt;
&lt;/plugin&gt;</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

backend developmentperformance testingSpring BootVirtual ThreadsProject LoomJava Concurrency
macrozheng
Written by

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.

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.