thunkware / virtual-threads-bridge

Use Java21's Virtual Threads API in Java 8+
MIT License
8 stars 3 forks source link

virtual-threads-bridge

Maven Central Javadoc

This library allows you to use Java21's Virtual Threads API in Java8+. You could then more easily write code that is compatible with both Java21 virtual threads and pre-Java21 platform threads.

For example, you might have your own Java8 or pre-Java21 library, and you want it to take advantage of virtual threads if your library is run on Java21 JVM. With virtual-threads-bridge you can write code like this:

ExecutorService executor = ExecutorTool.hasVirtualThreads()
    ? ExecutorTool.newVirtualThreadPerTaskExecutor()
    : Executors.newCachedThreadPool();

ExecutorService concurrencyLimitedExecutor = ExecutorTool.hasVirtualThreads()
    ? ExecutorTool.newSemaphoreVirtualExecutor(10)
    : Executors.newFixedThreadPool(10);

Thread thread = ThreadTool.hasVirtualThreads()
    ? ThreadTool.unstartedVirtualThread(myRunnable)
    : new Thread(myRunnable);


Of course, it's dangerous to blindly create excessive number of (platform) threads in Java8+/preJava21 without checking if virtual threads are available:

void processQueueMessage(...) {
   ThreadTool.startVirtualThread(this::process);  // dangerous in Java8+/preJava21
}

You can configure the library to throw exception if attempt is made to create virtual threads in Java8+/preJava21 (as opposed to creating in Java21):


public static void main(String ...) {
    // on app startup, configure library to throw exception if
    // startVirtualThread() is called in Java8+/preJava21
    ThreadTool.getConfig().throwExceptionWhen(START_VIRTUAL_THREAD);
}

void processQueueMessage(...) {
   ThreadTool.startVirtualThread(this::process);  // exception thrown here
}

Note that virtual threads do not have a thread name by default. To set names for threads, call:

// set name prefix globally for all threads created by this library
ThreadTool.getConfig().setThreadCustomizer(ThreadCustomizer.withNamePrefix("my-rpc-thread-"));

// set name prefix for threads in this Executor
ExecutorService executor = ExecutorTool.hasVirtualThreads()
    ? ExecutorTool.newVirtualThreadPerTaskExecutor(ThreadCustomizer.withNamePrefix("my-rpc-thread-"))
    : Executors.newCachedThreadPool();


The following Java21 APIs are bridged:

Java21 Bridge
Thread.isVirtual() ThreadTool.isVirtual(Thread)
Thread.ofPlatform() ThreadTool.ofPlatform()
Thread.ofVirtual() ThreadTool.ofVirtual()
Thread.startVirtualThread(Runnable) ThreadTool.startVirtualThread(Runnable)
Executors.newThreadPerTaskExecutor(ThreadFactory) ExecutorTool.newThreadPerTaskExecutor(ThreadFactory)
Executors.newVirtualThreadPerTaskExecutor() ExecutorTool.newVirtualThreadPerTaskExecutor()

Usage

Add the library to maven pom.xml (or the equivalent in your build system):

<dependency>
    <groupId>io.github.thunkware</groupId>
    <artifactId>virtual-threads-bridge</artifactId>
    <version>0.0.7</version>
</dependency>

License

This library is Open Source software released under the MIT license.