Controlling Java Async QPS with Semaphore and ThreadPool
This article explains how to use Java's java.util.concurrent.Semaphore together with a fixed-size thread pool to enforce a precise QPS limit for asynchronous tasks, providing API details, implementation steps, and a complete test example.
API Overview
Constructor: java.util.concurrent.Semaphore#Semaphore(int) – the integer sets the total number of permits.
Acquire permit: java.util.concurrent.Semaphore#acquire() – there are overloaded versions with timeout parameters.
Release permit: java.util.concurrent.Semaphore#release() – releases one permit by default.
Both acquire and release support multiple permits.
Implementation
The solution keeps the existing asynchronous thread‑pool mechanism and adds a semaphore to limit the QPS. Each task first acquires a permit, runs, sleeps for one second, then releases the permit.
Because the helper class com.funtester.frame.SourceCode is a Java utility, the implementation stays in Java and uses a Groovy‑to‑Java closure conversion to maintain compatibility.
/**
* Fixed QPS asynchronous execution, default 16, adjust via SourceCode#setMaxQps(int)
* @param f
*/
public static void funner(Closure f) {
if (!ThreadPoolUtil.acquire()) return;
fun(JToG.toClosure(() -> {
sleep(1.0);
fun(JToG.toClosure(() -> {
f.call();
ThreadPoolUtil.release();
return null;
}));
return null;
}));
}
/**
* Set the maximum QPS for asynchronous tasks
* @param i
*/
public static void setMaxQps(int i) {
ThreadPoolUtil.setSemaphore(new Semaphore(i));
}Global flow‑control variables:
/**
* Global flow control
*/
static Semaphore semaphore = new Semaphore(16);
static long AcquireTimeout = 8888;
/**
* Acquire a permit
*/
static boolean acquire() {
return semaphore.tryAcquire(AcquireTimeout, TimeUnit.MILLISECONDS);
}
/**
* Release a permit
*/
static def release() {
semaphore.release();
}Test Case
The test sets a low QPS (2) and repeatedly submits asynchronous tasks that print the current time.
static void main(String[] args) {
setMaxQps(2);
10.times {
funner {
output(Time.getDate());
}
}
}Sample console output shows tasks being throttled according to the QPS limit. A noted limitation is that when the thread pool becomes full, tasks may pile up; the article leaves this issue for future handling.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
