1

次のようなコードがあります。

final int THREADS = 11;  
BlockingQueue<Future<Long>> futureQueue = new ArrayBlockingQueue<Future<Long>>(THREADS);  
for (int i = 0; i < end; i++, count++) {  
    futureQueue.put(executor.submit(MyRunnable));  
}   
//Use queued results

これをリファクタリングしてより同時実行するにはどうすればよいですか? ここで私が監督している微妙な点はありますか?

更新:
各 Runnable は、ストレス テストのために大量の HTTP 要求をサーバーに送信することになっています。正しい軌道に乗っていますか?

4

2 に答える 2

3

私は使うだろう

static final int THREADS = Runnable.getRuntime().availableProcesses();  

ExecutorService service = Executors.newFixedThreadPool(THREADS);

List<Future<Long>> futureQueue = new ArrayList<Future<Long>>(end);  
for (int i = 0; i < end; i++)
    futureQueue.add(executor.submit(new MyRunnable()));  

制限付きキューを使用しており、end > THREADSそれが停止する場合。

各 Runnable は、ストレス テストのために大量の HTTP 要求をサーバーに送信することになっています。

その場合、コードは CPU バウンドではなく IO であるため、次を使用します。

ExecutorService service = Executors.newCachedThreadPool();

1000 を超えるスレッドがある場合は NIO を使用することでメリットが得られる可能性がありますが、これはロード テスターをより効率的にするだけで、コードはより複雑になります。(これが難しいと思われる場合は、効率的で正しいセレクター コードを記述することははるかに困難です)

テスターを複数のマシンで実行すると、さらに大きな違いが生じます。

于 2012-08-09T07:25:10.027 に答える
3

あなたの場合、スレッドの使用はうまくいきません。スレッド プールは、CPU を集中的に使用するジョブがある場合にうまく機能します。あなたの場合、IO 集中型のジョブがあります。これは、使用している CPU の数ではなく、送信できるネットワーク パケットの数によって制限されます。

この場合、NIO のクラスはあなたの味方です。何百もの接続を作成し、NIO セレクターを使用して、どれがより多くのデータを受信する準備ができているかを確認します。

このアプローチを使用すると、スレッドはまったく必要ありません。1 つの CPU コアは、GBit イーサネット接続 (~100MB/s) でさえ十分に満たすことができます。

[編集]もちろん、何百ものスレッドを作成して IO チャネルを埋めようとすることもできます。ただし、これにはいくつかの欠点があります。

  1. スレッドは OS (または小さなヘルパー ライブラリ) によって管理されます。メモリが必要で、スレッドが切り替わるたびに、CPU はその状態を保存してキャッシュをフラッシュする必要があります。
  2. スレッドが少量の作業しか行わない場合、スレッドの切り替えは作業を行うよりもコストがかかる可能性があります。
  3. スレッドを使用すると、通常のスレッド同期の問題がすべて発生します。
  4. 適切な量​​のスレッドがあることを確認する簡単な方法はありません。スレッドが少なすぎると、IO チャネルが最適に使用されません。スレッドが多すぎると、スレッドがチャネルへのアクセスを求めて競合するため、チャネルは最適に使用されません。どちらの場合も、テストの開始後にこれを変更することはできません。システムはニーズに適応しません。

このようなタスクには、これらすべての問題を回避し、スレッドよりも簡単に使用できるため、 Akkaのようなフレームワークがはるかに適しています。

于 2012-08-09T07:33:19.890 に答える