How do you create and use virtual threads, including in Spring Boot?

Java 21 offers several ways to start virtual threads: Thread.ofVirtual(), Thread.startVirtualThread() and Executors.newVirtualThreadPerTaskExecutor(). In Spring Boot 3.2 and later, a single property switches the web server and async tasks to virtual threads.

Key Points: • Thread.startVirtualThread(runnable) starts one immediately. • Thread.ofVirtual().name("worker-", 0).start(runnable) uses a builder to set names and options. • Executors.newVirtualThreadPerTaskExecutor() creates a new virtual thread for each submitted task. It is the usual choice for existing ExecutorService code. • Spring Boot: add spring.threads.virtual.enabled=true to application.properties. Tomcat, @Async, @Scheduled and others then run on virtual threads. • Existing blocking code (JDBC, RestTemplate) benefits without rewriting it as reactive code.

Code Example:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CreateVirtualThreads {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 1. Start directly
        Thread t1 = Thread.startVirtualThread(() -> System.out.println("Hello from a virtual thread"));
        t1.join();

        // 2. Builder with a name
        Thread t2 = Thread.ofVirtual().name("order-worker-", 1)
                .start(() -> System.out.println("Running in " + Thread.currentThread().getName()));
        t2.join();

        // 3. Executor: one virtual thread per task
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            Future<String> price = executor.submit(() -> "Price: 499");
            Future<String> stock = executor.submit(() -> "Stock: 12");
            System.out.println(price.get() + ", " + stock.get());
        }

        System.out.println("t1 virtual? " + t1.isVirtual());
    }
}

Output:

Hello from a virtual thread Running in order-worker-1 Price: 499, Stock: 12 t1 virtual? true

Good to Know: For a Spring Boot role, mention the property spring.threads.virtual.enabled=true and say you would load test before and after, watching for pinning and for limits elsewhere (such as the database connection pool), which become the next bottleneck.

Interview Tip: A concise interview answer is:

"I create them with Thread.startVirtualThread, Thread.ofVirtual().start, or most often Executors.newVirtualThreadPerTaskExecutor, which gives each task its own virtual thread. In Spring Boot 3.2+, I enable them with spring.threads.virtual.enabled=true, so Tomcat and @Async use virtual threads without code changes."

Previous question: When should you not use virtual threads, and what is thread pinning?

More Java 17 and 21 Features interview questions

All Java 17 and 21 Features questions