私はThread
がError
(Exception
ではなく)を投げる可能性があるマルチスレッドプロジェクトに取り組んでいます。マルチスレッドでエラーがどのように処理されるかについての確固たる情報が見つからないので、私はいくつかのテストを行うことにしました。結果は矛盾することがあります。Javaはマルチスレッドでエラーをどのように処理しますか?
これは私のテストコードと、コメントの結果です。
public class MultiThreadError {
public static class ErrorThrowingRunnable implements Runnable{
private final boolean throwsError;
public ErrorThrowingRunnable(boolean throwsError){
this.throwsError = throwsError;
}
@Override
public void run() {
try {
// Wait between .5 and 1.5 seconds
Thread.sleep(500 + new Random().nextInt(1000));
} catch (InterruptedException ex) {}
if(throwsError){
throw new Error(Thread.currentThread().getName());
}else{
System.out.println(Thread.currentThread().getName());
}
}
}
public static void regularThreadPool(){
// Crashes individual thread; swallows error
ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.submit(new ErrorThrowingRunnable(false));
threadPool.submit(new ErrorThrowingRunnable(false));
threadPool.submit(new ErrorThrowingRunnable(false));
threadPool.submit(new ErrorThrowingRunnable(false));
threadPool.submit(new ErrorThrowingRunnable(true));
threadPool.shutdown();
}
public static void onDemandThreads(){
// Crashes individual thread; displays error
new Thread(new ErrorThrowingRunnable(false)).start();
new Thread(new ErrorThrowingRunnable(false)).start();
new Thread(new ErrorThrowingRunnable(false)).start();
new Thread(new ErrorThrowingRunnable(false)).start();
new Thread(new ErrorThrowingRunnable(true)).start();
}
public static void onDemandThreadPool(){
// Same as onDemandThreads()
ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(true));
threadPool.shutdown();
}
public static void tooSmallThreadPool(){
// When an error is thrown, apparently the thread that threw
// the error is not reused, reducing the pool size
ExecutorService threadPool = Executors.newFixedThreadPool(3);
threadPool.execute(new ErrorThrowingRunnable(true));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.execute(new ErrorThrowingRunnable(false));
threadPool.shutdown();
}
}
エラーが発生したスレッドが終了し、メッセージを表示していることが予期されたものと思われます。 Runnable
がExecutorService
にsubmit(Runnable)
を使用して渡されたときには、エラーを処理しないRunnableFuture<Void>
にラップされていますが、何らかの理由で直接execute(Runnable)
を呼び出す以外にこの動作を変更する方法が見つからないことが判明しています同じ挙動を示す。
これには「ベストプラクティス」がありますか?スレッドがエラーをスローする可能性がある場合は、submit
をExecutorServiceに送信し、エラーを取り込まない方法がありますか?
ウィースタイルのノートでは、「エラー」を投げないようにしてください。彼らはあなたがとにかく対処しようとするべきではない重大な問題(メモリ不足など)を示します。 'Runnable'から何かを投げたい場合は、' RuntimeException'(またはそのサブクラス)を使うべきです。 –
[Java ExecutorServiceタスクから例外を処理する]の可能な複製(0120-18752) –
「RunnableFuture」_handles_エラーちょうど良い。実行可能なすべての呼び出しはtry/finallyでラップされます。あなたは私が疑うエラーメッセージを見ることができないと言っています。 – Gray