import java.util.concurrent.*;
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command)
throws InterruptedException {
semaphore.acquire();
try {
exec.execute(new Runnable() {
public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
}
}
public static void main(String...args) {
ExecutorService exec = Executors.newCachedThreadPool();
BoundedExecutor bexec = new BoundedExecutor(exec, 2);
try {
bexec.submitTask(new Runnable(){
public void run() {
System.out.println("tasks1");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
bexec.submitTask(new Runnable(){
public void run() {
System.out.println("tasks2");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
bexec.submitTask(new Runnable(){
public void run() {
System.out.println("tasks3");
}
});
exec.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The above example used a semaphore to throttle task submission. When the bound is set to 2, the third task submission blocked until one of the existing runnable finishes and releases a semaphore slot.