2017-03-06 3 views
1

J'ai un service qui utilise un pool de threads fixe car plus de 10 instances de cette tâche lourde seront trop lourdes pour mon serveur.ExecutorService avec n threads et n objets correspondants

ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10); 

Je l'utilise quelque chose comme:

Runnable command = new Runnable() { 
     @Override 
     public void run() { 
      MyHeavyClassWithCache myHeavyClassWithCache=new MyHeavyClassWithCache(); 
     } 
    }; 
    Future<ScreenImage> feature = executor.submit(command,myHeavyClassWithCacheResult); 

Maintenant, je dois aussi que les instances n (10) de la classe MyHeavyClassWithCache. Et aussi besoin de le réutiliser en quelque sorte dans l'exécuteur (beaucoup plus vite que de le créer comme je le fais maintenant). Comment puis-je gérer ce genre de chose avec ExecutorService? L'objectif est d'atteindre ce maximum de 10 threads fonctionnant en même temps en utilisant l'une de mes 10 instances de classe MyHeavyClassWithCache (jamais deux threads avec les mêmes instances en même temps!)

J'espère que c'est assez commun pour exister certains java modèle de conception pour y parvenir.

+1

Ce que vous cherchez est un pool d'objets. Vous pouvez utiliser commons-pool pour l'implémenterhttp: //commons.apache.org/proper/commons-pool/ – seneque

+0

Oui c'est ce dont j'ai besoin. Je l'ai mis en place et ça marche bien jusqu'à présent. Écrivez votre commentaire comme réponse ici. Merci beaucoup! –

Répondre

0

L'objectif est d'atteindre que 10 fils max travaillant en même temps en utilisant l'un de mes 10 instances de la classe MyHeavyClassWithCache

Il y a deux façons de le faire. Le plus simple est d'utiliser un ThreadLocal<MyHeavyClassWithCache> afin que chacun des threads de pool obtienne sa propre classe "lourde". Vos instances Runnable définiraient le ThreadLocal.

L'alternative serait de soumettre 10 HeavyRunnable instances à votre pool, chacune avec leur propre instance locale de MyHeavyClassWithCache et ont les dequeue d'un BlockingQueue différent. C'est un modèle que j'ai utilisé auparavant.

Le code pourrait ressembler à:

// runnable that dequeues from a blocking queue and keeps a heavy instance 
private static class HeavyRunnable implements Runnable { 
    private final MyHeavyClassWithCache heavy = new MyHeavyClassWithCache(); 
    private final BlockingQueue<Runnable> runnableQueue; 
    public HeavyRunnable(BlockingQueue<Runnable> runnableQueue) { 
     this.runnableQueue = runnableQueue; 
    } 
    public void run() { 
     while (!Thread.currentThread.isInterrupted()) { 
      Runnable runnable = runnableQueue.take(); 
      // if we see a null then stop running 
      if (runnable == null) { 
       break; 
      } 
      runnable.run(); 
     } 
    } 
} 

... 
final ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10); 
final BlockingQueue<Runnable> runnableQueue = new LinkedBlockingQueue<>(); 
newFixedThreadPool.add(new HeavyRunnable(runnableQueue)); 
... 
runnableQueue.add(new Runnable() { ... }); 
... 

Il est un peu difficile d'arrêter ces arrière-plan lourds runnables mais mettre 10 null s dans la file d'attente et ayant l'arrêt des threads quand ils DEQUEUE null est une façon .