Contents

How to create virtual threads Java 21

Written by: David Vlijmincx

Introduction

With Java 21, we get a new kind of thread, Virtual threads! In this post, we take a pragmatic approach to learn how you can create them.

Virtual threads are a new kind of thread and don't have a 1 to 1 relation with real OS threads. Instead, virtual threads have a many-to-one relation with OS threads.

Creating a Virtual Thread

The following example shows you how to create a virtual thread. The first example shows how to use the static builder method that takes a runnable as a parameter and immediately starts the virtual thread.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Runnable runnable = () -> {
    System.out.println("Hello, world!");
};

// Using a static builder method.
Thread virtualThread = Thread.startVirtualThread(runnable);

// Using a builder
Thread.ofVirtual()
        .name("my-virtual-thread")
        .start(runnable);

On line 7, the new builder is used to create a virtual thread. You can use the builder to set certain properties like the name.

ExecutorService with Virtual Threads

Since java 5, you are encouraged to use the ExecutorServices instead of the Thread class directly. With Java 21 we get a new ExecutorService that uses virtual threads. In the following example, an ExecutorService is created inside a try-with-resource statement that creates virtual threads for each submitted task. In this example, ten virtual threads are created that each print “Hello, world!” to the console.

1
2
3
4
5
6
7
8
9
Runnable runnable = () -> {
    System.out.println("Hello, world!");
};

try (ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i = 0; i < 10; i++) {
        executorService.submit(runnable);
    }
}

We can place an ExecutorService inside a try-with-resource because it now extends the AutoCloseable interface. The code in the example will exit the try-with-resource when all the virtual threads that were created are finished.

Virtual Thread Factory

You can also create a factory that creates virtual threads for you. In the following example, a virtual thread factory is created. Every virtual thread will have a name that is prefixed with “prefix” and end with a number.

On line 9, the factory is used to create virtual threads.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Runnable runnable = () -> {
    System.out.println("Hello, world!");
};

ThreadFactory virtualThreadFactory = Thread.ofVirtual()
        .name("prefix", 0)
        .factory();

Thread factoryThread = virtualThreadFactory.newThread(runnable);
factoryThread.start();

Conclusion

In this post, you learned how to create virtual threads in the most common ways. If you are curious about virtual threads, take a look at the following resources to learn more about them: