57

負荷とパフォーマンスのテストを行っているため、クライアント コードのエンド ツー エンドのパフォーマンスを測定するために複数のスレッドを生成する必要があるマルチスレッド プロジェクトに取り組んでいます。そこで、を使用している以下のコードを作成しましたExecutorService

以下はコードです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
    }   
}

問題文:

今、私はインターネットでいくつかの記事を読んでいました。もあることがわかりましたThreadPoolExecutor。そのため、どちらを使用すればよいか混乱しました。

上記のコードを次のコードから置き換えると:

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());
    }

これは何か違いがありますか?ExecutorServiceを使用して元のコードと を使用して貼り付けた新しいコードの違いを理解しようとしていThreadPoolExecutorます。私のチーム メイトの何人かは、2 番目のもの (ThreadPoolExecutor) が正しい使用方法であると言いました。

誰かが私のためにこれを明確にすることができますか?

4

6 に答える 6

83

のソースは次のExecutors.newFixedThreadPoolとおりです。

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

上記のように、デフォルト構成のクラスを内部的に使用ThreadPoolExecutorします。現在、優先度キューの代わりに使用する必要があるなど、デフォルト構成が適切でないシナリオがあります。そのような場合、呼び出し元は、それをインスタンス化し、必要な構成を渡すことによってLinkedBlockingQueue、基礎となるもので直接作業でき ます。ThreadPoolExecutor

于 2013-04-23T06:02:25.643 に答える
30

それは違いを生むでしょうか?

コードが複雑になり、ほとんどメリットがありません。

ExecutorService を使用している元のコードと、貼り付けた ThreadPoolExecutor を使用している新しいコードの違いを理解しようとしています。

何もない。 Executors実際の作業を行う ThreadPoolExecutor を作成します。

私のチーム メイトの何人かは、2 番目のもの (ThreadPoolExecutor) が正しい使い方だと言いました。

より複雑だからといって、それが正しいことであるとは限りません。設計者が Executors.newXxxx メソッドを提供したのは、作業を簡単にするためであり、これらのメソッドを使用することを期待していたからです。それらも使用することをお勧めします。

于 2013-04-23T05:59:24.300 に答える
14
  1. Executors#newFixedThreadPool(int nThreads)

    ExecutorService executor = Executors.newFixedThreadPool(20);
    

基本的に

 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);

2 番目のケースでは、maxPoolSize を 2000 に増やしているだけですが、これが必要になるとは思えません。

于 2013-04-23T06:01:36.697 に答える
4

RejectionHandler にはもう 1 つの利点があると思います。間違っている場合は修正してください

于 2014-04-21T22:40:13.730 に答える
1

の 2 日後GC out of memory exceptionThreadPoolExecutor私の命を救いました。:)

バラジが言ったように、

[..] もう 1 つの利点は、RejectionHandler を使用することです。

私の場合RejectedExecutionException、破棄ポリシーを(次のように)たくさん指定して、すべての問題を解決しました。

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

しかし、注意してください!エグゼキューターに送信するすべてのスレッドを実行する必要がない場合にのみ機能します。

詳細についてThreadPoolExecutorは、ダレンの回答をご覧ください

于 2015-11-10T10:03:36.133 に答える