import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
* Virtual thread utils (JDK 21+).
*
* @author Tong Li
*/
public class TioVirtualThreadUtils {
private static volatile ExecutorService virtualThreadExecutor;
static {
start();
}
private static ThreadFactory namedVirtualThreadFactory(String baseName) {
AtomicInteger threadNumber = new AtomicInteger(1);
return r -> Thread.ofVirtual().name(baseName + "-" + threadNumber.getAndIncrement()).unstarted(r);
}
public static ExecutorService getExecutor() {
return virtualThreadExecutor;
}
public static <T> Future<T> submit(Callable<T> task) {
return virtualThreadExecutor.submit(task);
}
public static <T> Future<T> submit(Runnable task, T result) {
return virtualThreadExecutor.submit(task, result);
}
public static Future<?> submit(Runnable task) {
return virtualThreadExecutor.submit(task);
}
public static void execute(Runnable runnable) {
virtualThreadExecutor.execute(runnable);
}
* Start executor if not started. Uses a per-task virtual thread executor,
* suitable for IO-bound workloads.
*/
public static void start() {
if (virtualThreadExecutor == null) {
virtualThreadExecutor = Executors.newThreadPerTaskExecutor(namedVirtualThreadFactory("tio-vt"));
}
}
public static void restart() {
stop();
start();
}
* Stop executor immediately. Note: shutdownNow() will attempt to interrupt
* running tasks.
*/
public static void stop() {
if (virtualThreadExecutor != null) {
virtualThreadExecutor.shutdownNow();
virtualThreadExecutor = null;
}
}
}