Thread API
The following use a static factory method to create a virtual thread, invokes its start method to schedule it, and then invokes the join method to wait up to 5 seconds for thread to terminate.
var thread = Thread.newThread(Thread.VIRTUAL, () -> System.out.println("hello")); // unstarted thread.start(); thread.join(Duration.ofSeconds(5));
The Thread.Builder API can also be used to creates virtual thread. The first example creates a virtual thread but does not start it. The second example creates and starts the virtual thread.
Thread thread1 = Thread.builder().virtual().task(() -> System.out.println("hello")).build(); Thread thread2 = Thread.builder().virtual().task(() -> System.out.println("hi")).start();
The Thread.Builder API can also be used to create a ThreadFactory. The ThreadFactory created by the following snippet will create virtual threads named "worker-0", "worker-1", "worker-2", ...
ThreadFactory factory = Thread.builder().virtual().name("worker", 0).factory();
ExecutorService API
The following creates an ExecutorService that runs each task in its own virtual thread. The example runs two tasks and selects the result of the first task to complete. The other task is cancelled and the virtual thread running it is interrupted. The example uses the try-with-resources construct to ensure that the ExecutorService is shutdown and that all tasks (or virtual threads in this example) complete before continuing.
try (ExecutorService executor = Executors.newUnboundedVirtualThreadExecutor()) { Callable<String> task1 = () -> "foo"; Callable<String> task2 = () -> "bar"; String result = executor.invokeAny(List.of(task1, task2)); }
The following creates an ExecutorService that runs each task in its own virtual thread. It adds a deadline to interrupt the threads that are still running when the deadline is reached.
Instant deadline = Instant.now().plusSeconds(30); try (ExecutorService executor = Executors.newUnboundedExecutor(factory).withDeadline(deadline)) { : }
Appendix: Differences between regular Threads and virtual Threads
Thread API
- VirtualThread always report their priority as NORM_PRIORITY. The priority is not inherited and cannot be changed with the setPriority method.
- Virtual threads are daemon threads. Their daemon status cannot be changed with the setDaemon method.
- Virtual threads cannot be suspend, resumed or stopped with the Thread suspend, resume and stop APIs.
- Virtual threads have no permissions when running with a security manager.
- Virtual threads are not active threads in their thread group. The getThreadGroup method returns a ThreadGroup that cannot be destroyed and its enumerate methods do not enumerate the virtual threads in the group.
Networking APIs
If a virtual thread is interrupted when blocked in an I/O operating on a java.net.Socket, ServerSocket or DatagramSocket then it causes IOException to be thrown.