Creating Virtual Threads

APIs

CodeMeaning
Thread.startVirtualThread(task)create and start one
Thread.ofVirtual().name("v-", 0).start(task)builder with names v-0, v-1...
Thread.ofVirtual().unstarted(task)create without starting
Executors.newVirtualThreadPerTaskExecutor()new virtual thread for every submitted task (no pooling)
thread.isVirtual()check

Hello Virtual Threads

Example

import java.util.*;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread v = Thread.ofVirtual().name("order-worker").start(() ->
                System.out.println("Hello from " + Thread.currentThread().getName()
                        + ", virtual=" + Thread.currentThread().isVirtual()));
        v.join();

        String[] results = new String[3];
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            final int id = i;
            threads.add(Thread.ofVirtual().name("v-", 0).start(() -> results[id] = "task " + id + " done"));
        }
        for (Thread t : threads) t.join();
        System.out.println(Arrays.toString(results));
        System.out.println("main is virtual? " + Thread.currentThread().isVirtual());
        System.out.println("virtual threads are daemon? " + Thread.ofVirtual().unstarted(() -> {}).isDaemon());
    }
}

Output

Hello from order-worker, virtual=true
[task 0 done, task 1 done, task 2 done]
main is virtual? false
virtual threads are daemon? true

10,000 Blocking Tasks

Example

Each task sleeps 1 second (like a slow DB call). With 10,000 virtual threads they all wait at the same time, so the whole job takes about 1 second. A pool of 100 platform threads would need about 100 seconds.

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) throws Exception {
        long start = System.nanoTime();
        try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
            List<Future<Integer>> futures = IntStream.range(0, 10_000)
                    .mapToObj(i -> executor.submit(() -> {
                        Thread.sleep(1000);       // blocking call: the virtual thread unmounts
                        return i;
                    }))
                    .toList();
            long sum = 0;
            for (Future<Integer> f : futures) sum += f.get();
            System.out.println("Tasks completed: " + futures.size() + ", sum of ids = " + sum);
        }
        long seconds = (System.nanoTime() - start) / 1_000_000_000;
        System.out.println("Finished in under 5 seconds: " + (seconds < 5));
    }
}

Output

Tasks completed: 10000, sum of ids = 49995000
Finished in under 5 seconds: true