リソースを大量に消費するコードを並行して実行したい場合は、AFAIKのsubmiting Callable/ Runnabletoが最適です。ExecutorServiceしたがって、私のメソッド構造:
public class ServiceClass {
protected final ExecutorService executorService = Executors.newCachedThreadPool();
public Future<Result> getResult(Object params) {
if (params == null) {
return null; // In situations like this the method should fail
}
// Do other fast pre-processing stuff
return executorService.submit(new CallProcessResult(params));
}
private class CallProcessResult implements Callable<Result> {
private Object params;
public CallProcessResult(Object params) {
this.params = params;
}
@Override
public Result call() throws Exception {
// Compute result for given params
// Failure may happen here too!
return result;
}
}
}
public class Result {
...
}
上記のコードで、障害が発生する可能性のある2つのスポットをマークしました。エラー処理に使用できるオプションは、これら2つの場合ではまったく異なります。
タスクを送信する前に、無効なパラメータ、失敗する可能性のある高速前処理コードなどの問題が発生する可能性があります。
ここで失敗を示すいくつかの方法があります。
- 無効の場合は、すぐにnull
paramsを返します。この場合、呼び出すたびにnullが返さgetResultれるかどうかを確認する必要があります。getResult - 上記の代わりにチェック済みの例外をスローします。
Future<Result>要求に応じてnullを返すaをインスタンス化しますget()。私はApacheCommonsでそれを行いConcurrentUtils.constantFuture(null)ます。getResultこの場合、私は常にnull以外の値を返すことを期待しますFuture<Result>。2番目のケースと一致しているので、このオプションの方が好きです。
タスクの実行中に、メモリ不足、破損したファイル、使用できないファイルなどの重大なエラーが発生する可能性があります。
- タスクの結果はオブジェクトであるため、私の場合のより良いオプションはnullを返すことだと思います。
- また、チェックされた例外をスローして処理することもできます
ThreadPoolExecutor.afterExecute(NiranjanBhatによって提案されたように)。JavaExecutorServiceタスクからの例外の処理を参照してください。
どちらがより良い習慣ですか(どちらの場合も)?
おそらく、これを行う別の方法や、使用する必要のあるデザインパターンがありますか?