面白いことが起こります…executorcompletionservice
-
10-10-2019 - |
質問
Javaに書かれたアプリケーションがあり、ネットワーク上のすべての到達可能なホストを見つける必要があります。
私が使う InetAddress.isReachable()
2000ミリ秒のタイムアウトでこれを行うには。
現在のローカルマシンのIPアドレスを検索し、ローカルマシンIPアドレスを逃した1〜255を終了する他のIPアドレスに到達しようとします。
それはすべて正常に動作しますシングルスレッドで動作しますが、ほとんどのIPアドレスは存在しないために到達できないため、2秒のタイムアウトを使い果たすため、長い時間がかかります。
物事をスピードアップするために(そして、アクションの並行性を試してみてください:: Brian Goetz)私は使用しようとしました Future
と Callable
等
これもすべてうまくいきました。
しかし、私は使用して空想しました ExecutorCompletionService
ユーザーにより応答性の高いアプリケーションを提供するために、使用可能になったときに結果が表示される可能性があります
Future<Reach> reachedFuture = completionService.take();
これを次の構成で単一プロセッサマシンで実行すると、4つの到達可能なホストのうち1つだけが識別されます。
private static final int poolSize = 10;
private static final int maxPoolSize = 10;
private static final long keepAliveTime = 120;
private static final LinkedBlockingQueue<Runnable> queue
= new LinkedBlockingQueue<Runnable>(20);
private static final ExecutorService executorService
= new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
private static final CompletionService<Reach> completionService
= new ExecutorCompletionService<Reach>(executorService);
クアッドコアマシンでこれを変更すると、すべての到達可能なホストを検出できませんでした。
private static final int poolSize
= Math.max(2,Runtime.getRuntime().availableProcessors());
private static final int maxPoolSize
= Math.max(2,Runtime.getRuntime().availableProcessors());
変更することによって InetAddress.isReachable()
タイムアウトは10秒になり、最後の構成作業はOKになりました。
また、Quad Coreマシンの次のように構成を変更することにより、2秒のタイムアウトでも動作しました。
private static final int poolSize = 2;
private static final int maxPoolSize = 2;
なぜこれが起こるのか非常に明白なものが足りないのですか?
何が止まるか InetAddress.isReachable(2000)
私のネットワーク上のすべての到達可能なホストを検出することから?
なぜ複数を実行しようとするのか InetAddress.isReachable()
通話が失敗しますか?
解決
だから私は自分のMacに小さなテストスクリプトを書きましたが、プールのサイズに関係なく、失敗することはできません。私は変更しました LinkedBlockingQueue
それ以外の場合は無制限になるために、私はすべてのジョブを提出することができませんでした。また、しばらくすると isReachable()
方法はスローしていました ConnectException
だから私はそれを具体的に処理する必要がありました。これはあなたのコード @user423199の問題ですか?
これがコードです:
これを実行しているOSは何だと思いますか?特定のIPスタックは、同じプロセス内でICMPパケットを実行する複数のスレッドを好まない場合があります。私はすべての最新のオペレーティングシステムがそれについて賢いと思っていたでしょうが、これは潜在的な問題かもしれません。また、Java JREとOSスタックの間のバグかもしれません。
お役に立てれば。