0

私は長時間実行されているコードを持っていますが、それはリクエストでボロボロになり、リソースの使用率が高くなり、不要な同時実行の問題が発生します。私の解決策は、各スレッドが事前に定義された時間だけ待機する待機領域のようなものを用意することです。スレッドが待機中に新しい要求がない場合、スレッドは操作を続行します。新しいリクエストがあると、クロックが再びリセットされ、前のスレッドが解放されます。

以前にセマフォとカウントダウン ラッチを使用したことがありますが、この特定のシナリオではどちらも機能しません。これを手作業でコーディングする前に、それを行う標準的な方法があるかどうかを確認したかったのです。

4

2 に答える 2

5

私は長時間実行されているコードを持っていますが、それはリクエストでボロボロになり、リソースの使用率が高くなり、不要な同時実行の問題が発生します。

スロットルを使用する必要があるように思えExecutorServiceます。スレッドの数を固定し、新しいリクエストが来るたびに新しいスレッドが作成されないようにする必要があります。その後、プール内のスレッドの数を調整することで、スループットを最大化できます。

// only allow 10 concurrent requests
ExecutorService threadPool = Executors.newFixedThreadPool(10);
...
while (requestsComeIn) {
    threadPool.submit(yourRunnableRequest);
}
// you need to shut the pool down once no more requests come in
threadPool.shutdown();

リクエストを調整するには、RejectedExecutionHandler. 次のコードのようなものは、100 個の要素がキューに入った後にどのブロックが機能するかを示しています。

BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(100);
ThreadPoolExecutor threadPool =
      new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, queue);
// we need our RejectedExecutionHandler to block if the queue is full
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
       @Override
       public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
           try {
                // this will block the producer until there's room in the queue
                executor.getQueue().put(r);
           } catch (InterruptedException e) {
                throw new RejectedExecutionException(
                   "Unexpected InterruptedException", e);
           }
    }
});

私の解決策は、各スレッドが事前に定義された時間だけ待機する待機領域のようなものを用意することです。

で無料で入手できますThreadPoolExecutor。たとえば、1 つのコア スレッドと 10 の最大スレッドを割り当ててから、(たとえば) 指定し5L, TimeUnit.MINUTESて、5 つの余分なスレッドの 1 つが 5 分間休止状態の場合、シャットダウンすることができます。残念ながら、キューがいっぱいでない限りThreadPoolExecutor、はコア スレッドを超えて起動しないことに注意してください。したがって、キューに 100 個のものが入った後でのみ、2 番目のスレッドが割り当てられます。そのため、私は通常、core と max thread params を同じ値にします。

于 2013-10-01T16:22:19.450 に答える
2

制御を維持する最も簡単な方法は、キューを使用することです。現代のBlockingQueueクラスは素晴らしい仕事をしています。その後、キューの長さを変えることで調整できます。

実際に自分で作業を行う代わりに、キューに投稿Jobし、キューの反対側に 1 つ以上のスレッドを配置して、すべての作業を実行します。

実際には、この正確なアーキテクチャを実装するために用意された構造があり、 と呼ばれますExecutorService。他にも多くの使用例があります。

詳細については、 ExecutorServiceを参照してください。

于 2013-10-01T16:21:15.970 に答える