web-dev-qa-db-fra.com

Java Thread Pool avec une file d'attente limitée

J'utilise Java.util.concurrent 's Executors pour créer un pool de threads fixe pour exécuter des gestionnaires de requêtes pour un serveur Web:

static ExecutorService  newFixedThreadPool(int nThreads) 

et la description est:

Crée un pool de threads qui réutilise un ensemble fixe de threads fonctionnant à partir d'une file d'attente partagée illimitée .

Cependant, je recherche une implémentation de pool de threads qui fera exactement la même chose, sauf avec une file d'attente bornée . Existe-t-il une telle implémentation? Ou dois-je implémenter mon propre wrapper pour le pool de threads fixe?

32
Amir Rachum

Ce que vous voulez faire est de créer votre propre ExecutorService, probablement en utilisant ThreadPoolExecutor . ThreadPoolExecutor a un constructeur qui prend un BlockingQueue et pour obtenir une file d'attente limitée que vous utilisez par exemple ArrayBlockingQueue correctement construit pour la délimitation. Vous pouvez également inclure un RejectedExecutionHandler afin de déterminer ce qu'il faut faire lorsque votre file d'attente est pleine, ou vous accrocher à une référence à la file d'attente de blocage et utiliser les méthodes d'offre.

Voici un mini exemple:

BlockingQueue<Runnable> linkedBlockingDeque = new LinkedBlockingDeque<Runnable>(
    100);
ExecutorService executorService = new ThreadPoolExecutor(1, 10, 30,
    TimeUnit.SECONDS, linkedBlockingDeque,
    new ThreadPoolExecutor.CallerRunsPolicy());
38
lscoughlin

Créez un ThreadPoolexecutor et passez-y l'implémentation BlockingQueue appropriée. pour par exemple vous pouvez passer un ArrayBlockingQueue dans le constructeur ThreadPoolExecutor pour obtenir l'effet souhaité.

6
Suraj Chandran

Lorsque vous créez un ThreadPoolExecutor, vous pouvez lui attribuer un BlockingQueue et un RejectedExecutionHandler afin que vous puissiez contrôler ce qui se passe lorsque la limite est atteinte. Le comportement par défaut consiste à lancer une RejectedExecutionException.

Vous pouvez également définir votre propre thread factory pour contrôler les noms des threads et en faire des threads démons.

3
Peter Lawrey

J'ai résolu cela avec un Semaphore que j'utilise pour limiter les tâches soumises au ExecutorService.

Par exemple:

int threadCount = 10;
ExecutorService consumerPool = Executors.newFixedThreadPool(threadCount);

// set the permit count greater than thread count so that we 
// build up a limited buffer of waiting consumers
Semaphore semaphore = new Semaphore(threadCount * 100); 

for (int i = 0; i < 1000000; ++i) {
    semaphore.acquire(); // this might block waiting for a permit 
    Runnable consumer = () -> {
       try {
          doSomeWork(i);
       } finally {
          semaphore.release(); // release a permit 
       }
    };
    consumerPool.submit(consumer);
}
3
lance-java