Executors.newVirtualThreadPerTaskExecutor()
Creates a service that runs every task in its own virtual thread.
Available since: Java 21
Syntax
public static ExecutorService newVirtualThreadPerTaskExecutor()Return value
ExecutorServiceA service that creates a new virtual thread for every task.
Examples
A thousand waiting requests run in parallel:
int fetchPrice(int id) throws InterruptedException {
Thread.sleep(200);
return id % 10;
}
void main() throws Exception {
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
List<Future<Integer>> futures = new ArrayList<>();
for (int id = 0; id < 1000; id++) {
int x = id;
futures.add(executor.submit(() -> fetchPrice(x)));
}
int total = 0;
for (var f : futures) total += f.get();
IO.println("total = " + total);
}
}Output:
total = 4500Notes
A thousand tasks of 200 ms each finish in about 200 ms rather than 200 seconds: each one waits in its own virtual thread. There is no need to limit the number of threads; to limit the load on an external service use a Semaphore. Close the service with try-with-resources.
See also
- Thread.ofVirtual() — Creates a virtual thread — a lightweight thread you can start by the million.
- ExecutorService — A service that runs tasks on a pool of threads.
- ExecutorService.close() — Closes the pool and waits for all tasks; called automatically by try-with-resources.
Related recipes
In the tutorial
- Virtual threads — Virtual threads in Java 21+ — how they differ from ordinary threads, Thread.ofVirtual, newVirtualThreadPerTaskExecutor, thousands of tasks at once and limiting with a Semaphore.