いくつかの JMX Bean をクエリする複数の Callable があるため、それぞれがタイムアウトする可能性があります。値をポーリングしたいのですが、毎秒としましょう。最も素朴なアプローチは、それぞれを別のスレッドで開始することですが、スレッドの数を最小限に抑えたいと考えています。より良い方法でそれを行うには、どのオプションが必要ですか?
3 に答える
私の解釈では、一定の間隔でポーリングする必要のあるCallableオブジェクトがたくさんあります。スレッドプールを使用する場合の問題は、プールが最も遅いメンバーで汚染され、より速いメンバーが不足することです。
スケジューリングを制御できるように思われるので、指数バックオフアプローチを検討することをお勧めします。つまり、Callable Xが実行された後(そしておそらくタイムアウトした後)、スケジュールを変更する前に1秒ではなく2秒待機します。それでも失敗する場合は、4秒、次に8秒などに進みます。ScheduledThreadPoolExecutorを使用する場合は、これを行うための組み込みの方法が付属しており、設定された遅延後に実行をスケジュールできます。
一定のタイムアウトを設定すると、この戦略により、遅いプールによる独占に対するプールの感受性が低下します。この問題を完全に取り除くことは非常に困難です。クエリされたオブジェクトごとに個別のスレッドを使用することは、実際には飢餓に陥らないようにする唯一の方法であり、あなたが言うように、それは非常にリソースを消費する可能性があります。
もう1つの戦略は、プールを高速プールと低速プールにバケット化することです。オブジェクトがタイムアウトしている場合(たとえばN回以上)、オブジェクトを低速プールに移動します。これにより、高速プールが高速に保たれ、低速プールはすべて互いに邪魔になりますが、少なくとも高速プールが詰まることはありません。彼らがしばらくの間良い統計を持っているならば、あなたは彼らを再び速いプールに昇進させることができます。
私はロボティックに同意します...「cachedThreadPool」を実装すると、スレッドの数が最適なレベルに制限されると同時にタイムアウトが発生し、未使用のリソースが解放されるため、問題が解決します
受け取るとすぐにsubmit
-将来の結果へのハンドル。一定時間、その完了を待つことを決定できます。Callable
Future
Future<String> future = executorService.submit(callable);
try {
future.get(1, TimeUnit.SECONDS);
} catch ( TimeoutException e ) {
future.cancel(true);
} catch ...
タイムアウトを指定して get を呼び出すと、タスクが完了していない場合に例外を受け取ることができます。これは、開始されていないタスクと開始されたが完了していないタスクを区別しません。一方cancel
、ブール値のパラメーターを取るため、mayStopIfRunning
たとえば、まだスケジュールされていないタスクのみをキャンセルすることを選択できます。