「//fix this/」の記事インデックス

//fix this/ Javaコードの間違いをさがせ!


このシリーズは、あなたのコーディング・スキルを試すコーナーです。毎号オラクルのJavaエバンジェリストたちが、Javaコードに関する難問を出題し、正解と解説を掲載します。是非、毎号チャレンジして貴方のコーディング能力の向上にお役立て下さい。


第12回目 (Java Magazine 2014/Jan-Febからの出題)


1. 今回のテーマ 「エラー・ロギング」 

ThreadPoolExecutor 内で Runnableを実行中にスローされる例外を正しくロギングしたいと考えています。



2. コード

次のコードを思いつきましたが、これでは、Runnable を submitするすべてのコールサ イトを修正しなければなりません。もっと簡単な方法はないでしょうか。


final Future runnableSubmission = es.submit(new Runnable() {
  @Override
  public void run() {
   int computed = 1 / 0;
  }
});

es.submit(new Runnable() {
  @Override
  public void run() {
    try {
        runnableSubmission.get();
    } catch (InterruptedException | ExecutionException e) {
       LOG.log(Level.SEVERE, "Exception while executing task!", e);
    }
  }
});

3.正しいのはどれ?

上記のコードの正しい修正方法を選んでください。

1) ThreadPoolExecutor に ThreadFactory を追加する。つまり、作成したスレッドで、 UncaughtException Handler を設定する。

2) ThreadPoolExecutor を継承し、afterExecute メソッドをオーバーライドする。

3) ThreadPoolExecutorを継承し、Future submit(Runnable task)メソッドをオーバーライドして、それぞれの Runnable の後にチェック・タスクを追加する。

4) ThreadPoolExecutor を継承し、ExecutorService インタフェースに宣言されている3種類の submit メソッドすべてをオーバーライドする。

<ヒント>
JRE クラスは拡張可能です。






【答え】

正解は 2)(ThreadPoolExecutor を継承し、afterExecute メソッドをオーバーライドする)です。このメソッドの javadoc では、例外のロギングを例に挙げてafterExecute メソッドをオーバーライドする理由について説明しています。
この例の System.out.println を適切なロガー呼出しに変えるだけで作業は終了です。

選択肢の 1)は、例外が未処理のままでは残らないためうまく行きません。例外が ThreadPoolExecutor にキャッチされ、UncaughtExceptionHandler まで届きません。3)と4)は、エグゼキュータへのタスクの送信方法によってはうまく行かない場合があります。3)の方法では 4)に挙げられているメソッドが対象にならず、4)の方法では void execute(Runnable command) メソッドが対象になりません。
submit 関連のメソッドをオーバーライドするという実装方法では、すべての状況に対応するために、これら 4 つのメソッドをすべてオーバーライドする必要があります。


<< 第11回へ戻る I 第13回へ進む >>

「//fix this/」の記事インデックス