Design and Implementation of a Java Virtual Thread Asynchronous Task Framework
This article introduces a Java virtual‑thread based asynchronous task framework, detailing its design constraints, a thread‑safe task queue, daemon thread management, and overloaded execute methods for Runnable and Groovy Closure, along with code examples and performance testing considerations.
Design Overview
Recently I have been using JDK 21's virtual thread feature and found it highly valuable for performance testing. The official documentation lists handling many small asynchronous tasks as a primary use case, allowing threads to be created on demand and destroyed after use without complex thread‑management or synchronization.
Design Points
Do not create an unlimited number of virtual threads; instead, impose a maximum parallel virtual‑thread count.
Use a task‑queue design with a thread‑safe queue to store pending tasks.
Introduce a daemon thread (similar to the custom async keyword in the previous article) that fetches tasks from the queue and executes them.
Provide a utility method that adds tasks to the queue.
Code Implementation
Task Queue
/**
* Pending task queue, maximum capacity is MAX_WAIT_TASK
*/
static LinkedBlockingQueue
queue = new LinkedBlockingQueue(MAX_WAIT_TASK);This code creates a static LinkedBlockingQueue named queue to hold tasks of type Closure . The constant MAX_WAIT_TASK defines the queue's maximum capacity, preventing unbounded growth.
The add method inserts a task into the queue:
/**
* Add a task
* @param closure
* @return
*/
static def add(Closure closure) {
queue.add(closure)
}Execute Methods
Two overloaded execute() methods are provided: one accepts a java.lang.Runnable , the other a groovy.lang.Closure . Both start a virtual thread, adjust a shared counter, and run the supplied task.
/**
* Execute a task
* @param runnable
* @return
*/
static def execute(Runnable runnable) {
daemon()
Thread.startVirtualThread {
index.getAndIncrement()
SourceCode.noError {
runnable.run()
}
index.getAndDecrement()
}
}
/**
* Execute a task
* @param closure task closure
* @return
*/
static def execute(Closure closure) {
daemon()
Thread.startVirtualThread {
index.getAndIncrement()
SourceCode.noError {
closure()
}
index.getAndDecrement()
}
}The methods share the same workflow: ensure the daemon thread is running, start a virtual thread, modify the index counter, and invoke the provided task.
Daemon Thread
/**
* Daemon thread state, ensures it runs only once
*/
static AtomicBoolean DaemonState = new AtomicBoolean(false);
/** Maximum concurrent task count */
static int MAX_THREAD = 10;
/**
* Start the daemon thread, guaranteeing it stops after the main method ends
*/
static def daemon() {
def set = DaemonState.getAndSet(true);
if (set) return;
new Thread(new Runnable() {
@Override
void run() {
SourceCode.noError {
while (ThreadPoolUtil.checkMain()) {
while (index.get() < MAX_THREAD) {
def poll = queue.poll(100, TimeUnit.MILLISECONDS);
if (poll != null) {
execute(poll);
} else {
break;
}
}
sleep(0.3);
}
}
}
}, "FV").start();
}The daemon thread checks the main‑thread status, then repeatedly pulls tasks from the queue (with a 100 ms timeout) while the number of running tasks is below MAX_THREAD . Each retrieved task is executed via execute(poll) . The loop sleeps briefly to avoid busy‑waiting.
A helper method can wait for all queued tasks to finish:
waitFor {
VirtualThreadTool.queue.size() == 0
}Conclusion
The simple asynchronous task execution framework is now complete. It has been tested against Java virtual threads and Go's goroutine performance, confirming comparable efficiency. Virtual threads provide a lightweight concurrency model that can handle massive parallelism, making them suitable for performance‑testing scenarios where high‑load behavior needs to be simulated and bottlenecks identified.
Although broader adoption of Java virtual threads in production services will take time, they are already ready for use in performance testing phases.
FunTester
10k followers, 1k articles | completely useless
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.