いかにして適切にチRuntimeExceptionsから執行者?
-
18-09-2019 - |
質問
とは言え、以下のコード:
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(myRunnable);
また、この myRunnable
投げ RuntimeExcpetion
, どうですか?ワンちょっと自分の供給 ThreadFactory
実装 newSingleThreadExecutor()
設定カスタム uncaughtExceptionHandler
sの Thread
s出てくるのです。別の言い方をするラップ myRunnable
現地(匿名) Runnable
を含むがtry-catchブロック.ん、ありがとうございまはその他類似の回避策のです。が---なんだかこう汚れを感じるべきではないこの複雑です。ある清潔なソリューション?
解決
クリーンな問題を回避するには、ExecutorService.submit()
の代わりにexecute()
を使用することです。これは、あなたがタスクの結果または例外を取得するために使用することができますFuture
を返します:
ExecutorService executor = Executors.newSingleThreadExecutor();
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
};
Future<?> future = executor.submit(task);
try {
future.get();
} catch (ExecutionException e) {
Exception rootException = e.getCause();
}
他のヒント
実行時例外をキャッチし、それらを処理する別の実行可能で実行可能なを飾るます:
public class REHandler implements Runnable {
Runnable delegate;
public REHandler (Runnable delegate) {
this.delegate = delegate;
}
public void run () {
try {
delegate.run ();
} catch (RuntimeException e) {
... your fancy error handling here ...
}
}
}
executor.execute(new REHandler (myRunnable));
なぜませ------------ ExecutorService#submit()
, を取得し Future
背対応可能なフレームワーク自分の通話の場合 Future#get()
?
skaffmanは、その使用submit
に正しいクリーンなアプローチです。別のアプローチは、 ThreadPoolExecutor
にサブクラス化することですそして、afterExecute(Runnable, Throwable)
をオーバーライドします。あなたがこのアプローチに従った場合の のexecute(Runnable)
呼び出してくださいではなく、submit(Runnable)
またはafterExecute
が呼び出されることはありません。
APIの説明毎ます:
メソッドの完了時に呼び出されます 与えられたRunnableの実行。この この方法は、そのスレッドによって呼び出されます タスクを実行します。 null以外の場合は、 Throwableがキャッチされていないです の
RuntimeException
またはError
の原因となっ 突然終了する実行ます。注:アクションはで囲まれています (FutureTaskなど)のいずれかのタスク 明示的に、またはのような方法による 提出し、これらのタスクオブジェクトをキャッチし、 計算の例外を維持し、 そう、彼らは突然起こしません 終了、および内部 例外は、これにを渡されていません 方法の。
仕事(Callable
または Runnable
) に提出する ThreadPoolExecutors
に変換されます FuturnTask
, 、という名前の小道具が含まれています callable
送信したタスクと同じです。FuturnTask には独自の run
以下のような方法で。すべての例外またはスロー可能オブジェクトがスローされる c.call()
捕らえられ、という名前の小道具に入れられます outcome
. 。FuturnTask を呼び出すとき get
方法、 outcome
投げられます
Jdk1.8ソースコードからのFuturnTask.run
public void run() {
...
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
// save ex into `outcome` prop
setException(ex);
}
if (ran)
set(result);
}
}
...
}
例外をキャッチしたい場合:
- 1.スカフマンの答え
- 2.ThreadPoolExecutor を新規作成するときに `afterExecute` を上書きします
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Throwable cause = null;
if (t == null && r instanceof Future) {
try {
((Future<?>) r).get();
} catch (InterruptedException | ExecutionException e) {
cause = e;
}
} else if (t != null) {
cause = t;
}
if (cause != null) {
// log error
}
}