0

メイン スレッドとは異なるスレッドからチェックされていない例外がスローされたときに、Eclipse のコンソールでスタック トレースを表示できないのはなぜですか?

例えば:

ScheduledThreadPoolExecutor scheduledExecutor;
scheduledExecutor.scheduleAtFixedRate(new Log(), 0, LOGGING_FREQUENCY_MS, TimeUnit.MILLISECONDS);
public class Log implements Runnable {
        public void run() {
     //NullPointerException is thrown
     }
}

出力がありません。しかし、もしそうなら:

ScheduledThreadPoolExecutor scheduledExecutor;
scheduledExecutor.scheduleAtFixedRate(new Log(), 0, LOGGING_FREQUENCY_MS, TimeUnit.MILLISECONDS);
public class Log implements Runnable {
        public void run() {
        try {
        //NullPointerException is thrown
        }catch(Exception e){
             e.printStackTrace();
        }
    }
}

スタック トレースが表示されます。

なんで?

編集:フォローアップの質問: スレッドプール スレッドによってスローされた例外を出力する最も簡単な方法は何ですか? もちろん、すべての Runnable に try-catch を追加するのは本当に見苦しいものです。

4

2 に答える 2

4

メイン スレッドとは異なるスレッドからチェックされていない例外がスローされたときに、Eclipse のコンソールでスタック トレースを表示できないのはなぜですか?

未チェックなので。デフォルトでは、スレッドプール スレッドによってスローされた例外を出力するものは何もありません。

例外を表示したい場合は、次のようにする必要があります。

Future future = scheduledExecutor.submit(...);
...
try {
   // wait for the run() method to finish normally or with a throw
   future.get();
} catch (ExecutionException e) {
   // the cause of this exception is the one that is thrown by the run()
   Throwable cause = e.getCause();
   cause.printStackTrace();
}

編集: フォローアップの質問: スレッドプール スレッドによってスローされた例外を出力する最も簡単な方法は何ですか? もちろん、すべての Runnable に try-catch を追加するのは本当に見苦しいものです。

try/catch を に追加する必要はありませんRunnable。プールを開始する人に追加します。

RunnableWrapper別の解決策は、例外を出力するちょっとしたものを書くことです:

public void RunnableWrapper implements Runnable {
     private Runnable delegate;
     public RunnableWrapper(Runnable delegate) {
       this.delegate = delegate;
     }
     public void run() {
         try {
            delegate.run();
         } catch (Throwable t) {
             t.printStackTrace();
         }
     }
 }

次に、次のことができます。

 scheduledExecutor.submit(new RunnableWrapper(myTask));

しかし、future.get();これはこれを解決する典型的な方法です。

于 2013-05-29T15:09:03.960 に答える
1

Executor が例外を「飲み込んだ」ためです。返された未来をクエリすることで、それを取得したかどうかを確認できます。

Future<?> f = scheduledExecutor.scheduleAtFixedRate(new Log(),...);
try {
    f.get();
} catch (ExecutionException e) {
    Throwable actualException = e.getCause();
}

タスクがキャンセルされるか例外がスローされるまでブロックされることに注意してください。そのf.get()ため、おそらく別のスレッドで呼び出すことをお勧めします。

于 2013-05-29T15:10:13.947 に答える