私が制御できないレガシー ライブラリと統合しています。
次のインターフェースが定義されています。
interface Factory {
Future<Void> subscribe(Context c);
}
この「subscribe」メソッドは、さまざまなスレッドによって頻繁に呼び出されます。「Future.get()」の結果が気になるのは、失敗したときだけなので、例外を取得して処理できます。これは、呼び出しスレッドで発生する必要はありません。さらに、「Future.get()」でスレッドの呼び出しをブロックすると、私の場合は非常にコストがかかる可能性があります。成功したとしても、いっぱいになるまでに数秒かかる場合があります。
したがって、私の仕事は、失敗したものをフィルタリングして、これらすべての先物を何らかの方法で「後処理」することです。基本的に、次の 2 つのアプローチが考えられます。
アプローチ #1:
Future のインスタンスを取得したら、必要な処理を行う別の Runnable を外部エグゼキューターに送信します。
executor.submit(
new Runnable(){
@Override
public void run() {
try {
future.get();
} catch(Exception e){
// process the exception
}
}
}
);
このアプローチの欠点は、スレッドを長時間ブロックしている可能性があることです。前述したように、このコード スニペットはかなり頻繁に実行されます。
アプローチ #2:
Future のインスタンスを取得したら、それを何らかのコレクションに配置し、処理を実行するこのコレクションの要素を定期的に実行する別の単一スレッドを専用にします。
while(true){
Iterator<Future<Void>> iterator = collection.iterator();
while(iterator.hasNext()){
Future<Void> future = iterator.next();
if(future.isDone()){
try {
future.get();
} catch(Exception e){
// process the exception
} finally {
iterator.remove();
}
}
}
TimeUnit.MILLISECONDS.sleep(1000); // sleep
}
どう思いますか?問題を解決するより良い方法はありますか?