J'ai eu le même problème et j'ai mis en œuvre que par l'utilisation d' beforeExecute/afterExecute
crochets ThreadPoolExecutor
:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Blocks current task execution if there is not enough resources for it.
* Maximum task count usage controlled by maxTaskCount property.
*/
public class BlockingThreadPoolExecutor extends ThreadPoolExecutor {
private final ReentrantLock taskLock = new ReentrantLock();
private final Condition unpaused = taskLock.newCondition();
private final int maxTaskCount;
private volatile int currentTaskCount;
public BlockingThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, int maxTaskCount) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
this.maxTaskCount = maxTaskCount;
}
/**
* Executes task if there is enough system resources for it. Otherwise
* waits.
*/
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
taskLock.lock();
try {
// Spin while we will not have enough capacity for this job
while (maxTaskCount < currentTaskCount) {
try {
unpaused.await();
} catch (InterruptedException e) {
t.interrupt();
}
}
currentTaskCount++;
} finally {
taskLock.unlock();
}
}
/**
* Signalling that one more task is welcome
*/
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
taskLock.lock();
try {
currentTaskCount--;
unpaused.signalAll();
} finally {
taskLock.unlock();
}
}
}
Ce devrait être assez bon pour vous. Btw, l'origine de la mise en œuvre était la tâche de la taille car une tâche pourrait être plus de 100 fois supérieur à un autre et la soumission de deux immenses tâches était en train de tuer la boîte, mais l'exécution d'un grand et beaucoup de petites allait bien. Si votre I/O des tâches à forte intensité sont à peu près de la même taille, vous pouvez utiliser cette classe, sinon faites le moi savoir et je vais poster la taille en fonction de la mise en œuvre.
P. S. Vous pouvez vérifier les ThreadPoolExecutor
javadoc. C'est vraiment très gentil guide de l'utilisateur de Doug Lea sur la façon dont il pourrait être facilement personnalisé.