ExecutorService vs ThreadPoolExecutor using LinkedBlockingQueue

je travaille sur un projet multithread dans lequel je dois générer plusieurs threads pour mesurer les performances de bout en bout de mon code client, pendant que je fais des tests de charge et de Performance. J'ai donc créé le code ci-dessous qui utilise ExecutorService.

ci-dessous se trouve le code avec ExecutorService:

public class MultithreadingExample {

    public static void main(String[] args) throws InterruptedException {

        ExecutorService executor = Executors.newFixedThreadPool(20);
        for (int i = 0; i < 100; i++) {
            executor.submit(new NewTask());
        }

        executor.shutdown();
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
    }
}

class NewTask implements Runnable {

    @Override
    public void run() {
        //Measure the end to end latency of my client code
    }   
}

énoncé du problème:

maintenant je lisais un article sur Internet. J'ai découvert il y a ThreadPoolExecutor. Donc, je me suis confondue avec qui je devriez être en utilisant.

Si je remplace mon code ci-dessus:

ExecutorService executor = Executors.newFixedThreadPool(20);
    for (int i = 0; i < 100; i++) {
        executor.submit(new NewTask());
    }

à:

BlockingQueue<Runnable> threadPool = new LinkedBlockingQueue<Runnable>();

ThreadPoolExecutor tpExecutor = new ThreadPoolExecutor(20, 2000, 0L, TimeUnit.MILLISECONDS, threadPool);

tpExecutor.prestartAllCoreThreads();

    for (int i = 0; i < 100; i++) {
        tpExecutor.execute(new NewTask());
    }

cela fera toute la différence? J'essaie de comprendre quelle est la différence entre mon code d'origine en utilisant ExecutorService et le nouveau code collé avec ThreadPoolExecutor. Certains de mes coéquipiers ont dit que la seconde (ThreadPoolExecutor) est la bonne façon d'utiliser.

quelqu'un peut-il clarifier ceci pour moi?

40
demandé sur Rodia 2013-04-23 09:53:23

6 réponses

Voici la source de Executors.newFixedThreadPool:

 public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

Il utilise en interne ThreadPoolExecutor classe avec la configuration par défaut comme vous pouvez le voir ci-dessus. Maintenant, il y a des scénarios où la configuration par défaut n'est pas appropriée, disons à la place de LinkedBlockingQueue une file d'attente prioritaire doit être utilisée, etc. Dans de tels cas, l'appelant peut travailler directement sur ThreadPoolExecutor en l'instanciant et en lui passant la configuration désirée.

62
répondu harsh 2013-04-23 06:02:25

alors cela fera une différence?

il va rendre votre code plus compliqué pour peu d'avantage.

j'essaie de comprendre quelle est la différence entre mon code original qui utilise ExecutorService et le nouveau code que j'ai collé qui utilise ThreadPoolExectuor?

à Côté de rien. Executors crée un ThreadPoolExecutor pour faire le vrai travail.

Certains de mes coéquipiers la deuxième (ThreadPoolExecutor) est la bonne façon d'utiliser?

ce n'est pas parce que c'est plus compliqué que c'est la bonne chose à faire. Les concepteurs ont fourni les exécuteurs.newXxxx méthodes pour rendre la vie plus simple pour vous et parce qu'ils s'attendaient à l'utilisation de ces méthodes. Je vous suggère de les utiliser ainsi.

22
répondu Peter Lawrey 2013-04-23 05:59:24
  1. Executors#newFixedThreadPool (int nThreads)

    ExecutorService executor = Executors.newFixedThreadPool(20);
    

est fondamentalement

 return new ThreadPoolExecutor(20, 20,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());

2.

BlockingQueue<Runnable> threadPool = new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor tpExecutor = new ThreadPoolExecutor(20, 2000, 0L,
    TimeUnit.MILLISECONDS, threadPool);

dans le second cas, vous augmentez le maxPoolSize à 2000, ce dont je doute que vous ayez besoin.

9
répondu NINCOMPOOP 2013-04-23 06:08:56

je crois un avantage de plus est avec RejectionHandler. Corrigez-moi si mal

4
répondu Balaji Boggaram Ramanarayan 2014-04-21 22:40:13

après 2 jours de GC out of memory exception,ThreadPoolExecutor a sauvé ma vie. :)

comme Balaji l'a dit,

[..] un avantage de plus est avec RejectionHandler.

Dans mon cas, j'ai eu beaucoup de RejectedExecutionException et en spécifiant (comme suit) la Politique de rejet a résolu tous mes problèmes.

private ThreadPoolExecutor executor = new ThreadPoolExecutor(1, cpus, 1, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.DiscardPolicy());

Mais attention! Il ne fonctionne que si vous ne pas besoin d'exécuter les fils que vous soumettez à l'exécuteur.

Pour plus d'informations sur ThreadPoolExecutor regardez la réponse de Darren

1
répondu Gloria 2017-05-23 12:26:26

dans le premier exemple, vous avez créé seulement 20 threads avec la déclaration ci-dessous

ExecutorService executor = Executors.newFixedThreadPool(20);

dans le second exemple, vous avez défini la plage des limites de thread entre 20 to 2000

 ThreadPoolExecutor tpExecutor = new ThreadPoolExecutor(20, 2000, 0L, 
                                     TimeUnit.MILLISECONDS,threadPool);

plus de threads sont disponibles pour le traitement. Mais vous avez configuré la file d'attente des tâches comme file d'attente illimitée.

ThreadPoolExecutor serait plus efficace si vous avez personnalisé beaucoup ou tous les paramètres ci-dessous.

ThreadPoolExecutor(int corePoolSize, 
               int maximumPoolSize, 
               long keepAliveTime, 
               TimeUnit unit, 
               BlockingQueue<Runnable> workQueue, 
               ThreadFactory threadFactory,
               RejectedExecutionHandler handler)

RejectedExecutionHandler serait utile lorsque vous définissez max capacity for workQueue et le nombre de tâches qui ont été soumises à L'exécuteur sont plus que workQueue capacité.

consultez la section Tâches rejetées dans ThreadPoolExecutor pour plus de détails.

1
répondu Ravindra babu 2016-05-09 08:57:23