2017-05-08 4 views
0

Dois-je créer un nouvel ExecutorService dans chaque appel de méthode ou en utiliser un par classe? Quelle est l'option préférée en termes de performance?ExecutorService - crée de nouvelles instances dans la méthode vs une par classe

public class NotificationService { 

    public void sendNotification(User recipient) { 

     ExecutorService notificationsPool = Executors.newFixedThreadPool(10); 

     // code 

     notificationsPool.shutdown(); 
    } 
} 

Ou

public class NotificationService { 

    ExecutorService notificationsPool = Executors.newFixedThreadPool(10); 

    public void sendNotification(User recipient) { 

     // code 
    } 
} 
+2

Vous ne choisissez pas cela en fonction des performances. Vous choisissez cela en fonction de ce qui est nécessaire. Avez-vous besoin de 10 nouveaux threads pour envoyer une notification à un utilisateur? Quel est l'intérêt d'avoir un pool de 10 threads réutilisables si vous n'en utilisez qu'un, une seule fois (en supposant que c'est ce que ferait l'envoi d'une notification à un utilisateur)? –

+0

L'utilisateur peut être associé à plus d'une clé. Cependant, ce n'est pas un bon exemple de code qui a été modifié avant de poster. – Justas

Répondre

1

Dans votre premier extrait de code est le ExecutorService local, à savoir une nouvelle ExecutorService est créée à chaque appel de la méthode et la ExecutorService se termine à la fin de la méthode. Par conséquent, les threads ne sont pas réutilisés lorsque la méthode s'exécute la prochaine fois. Dans le deuxième extrait, le ExecutorService et ses threads sont conservés tant que l'instance NotificationService est active. Comme vous pouvez le voir, il y a non seulement moins d'instances de ExecutorService à GC, mais il y a moins de threads à créer et ils peuvent être réutilisés. En tant que bonus supplémentaire, la seconde méthode n'entraîne aucun temps de préchauffage pour la création de threads après que le ExecutorService a été créé.

Si vous avez plusieurs instances de NotificationService, vous devez déclarer notificationsPool comme static afin de partager le pool et ses threads entre toutes les instances.

Si la quantité de threads requise varie en fonction de la quantité de notifications à envoyer, utilisez un pool de threads mis en cache (ExecutorService#newCachedThreadPool()), éventuellement avec une limite supérieure.

1

Cela dépend de deux questions:

  • quelle classe de parallélisation avez-vous besoin?
  • quelle quantité de frais généraux est acceptable pour vous?

Avez-vous vraiment besoin de 10 threads pour résoudre le problème dans la fonction? Et avez-vous besoin de pouvoir traiter la fonction deux fois (lui donnant ainsi 20 threads)? Avez-vous même les ressources pour le faire?

Ou que se passerait-il si vous allouer un threadPool à la classe? Souhaitez-vous probablement rencontrer des problèmes en faisant cela (blocage en raison de l'utilisation du pool de threads)?

Avec suffisamment de ressources, l'option 1 pourrait être plus rapide SI la tâche à résoudre est suffisamment importante pour justifier le surcoût de création de cet exécuteur à chaque fois que la fonction est appelée. Bien honnêtement, je ne peux guère imaginer une notification aussi intense.

Ainsi, sans plus d'informations, je pointerais vers l'option 2 (en supposant qu'elle soit statique bien sûr). Vous pouvez également jeter un coup d'oeil dans le nouveau WorkStealingPool, il pourrait vous aider à utiliser le niveau précis de parallélisme.