何千ものネットワーク リクエストを作成するユーティリティを作成しています。各要求は、応答として 1 つの小さなパケットのみを受信しますが (ping と同様)、完了するまでに数秒かかる場合があります。各応答の処理は、1 行の (単純な) コードで完了します。
これの最終的な効果は、コンピューターが IO バウンド、ファイル システム バウンド、または CPU バウンドではなく、応答の待機時間によってのみバインドされることです。
これは、理想的なスレッド数を決定する方法はありますか?と似ていますが、同じではありません。およびJavaの最適なスレッド数を決定する最良の方法[重複] ...主な違いは、レイテンシーのみに拘束されることです。
ExecutorService
オブジェクトを使用してスレッドを実行し、Queue<Future<Integer>>
結果を取得する必要があるスレッドを追跡します。
ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
Queue<Future<Integer>> futures = new LinkedList<Future<Integer>>();
for (int quad3 = 0 ; quad3 < 256 ; ++quad3) {
for (int quad4 = 0 ; quad4 < 256 ; ++quad4) {
byte[] quads = { quad1, quad2, (byte)quad3, (byte)quad4 };
futures.add(executorService.submit(new RetrieverCallable(quads)));
}
}
... 次に、キュー内のすべての要素をデキューし、結果を必要なデータ構造に入れます。
int[] result = int[65536]
while(!futures.isEmpty()) {
try {
results[i] = futures.remove().get();
} catch (Exception e) {
addresses[i] = -1;
}
}
私の最初の質問は、これはすべてのスレッドを追跡する合理的な方法ですか? スレッド X の完了に時間がかかる場合、他の多くのスレッドが X より先に終了する可能性があります。スレッド プールは、開いているスロットを待ってそれ自体を使い果たしますか? または、ExecutorService
オブジェクトは、完了したがまだ処理されていないスレッドを使用可能なスロットから移動して、他のスレッドを開始できるようにプールを管理しますか?
2 番目の質問は、これらの呼び出しを行うのに最適なスレッド数を見つけるために、どのガイドラインを使用できるかということです。ここでは桁違いのガイダンスさえ知りません。256 スレッドでうまく動作することはわかっていますが、1024 スレッドでも全体的にほぼ同じ時間がかかるようです。CPU 使用率は 5% 前後で推移しているため、問題はないようです。このように多数のスレッドがある場合、さまざまな数値を比較するために見なければならないすべてのメトリックは何ですか? 明らかに、バッチを処理するための全体的な時間、スレッドあたりの平均時間...他に何がありますか? ここでメモリは問題ですか?