1. ホーム
  2. java

[解決済み] JavaにおけるInterruptedExceptionの処理

2022-03-23 10:26:33

質問

次のような処理方法の違いは何ですか? InterruptedException ? どのような方法が良いのでしょうか?

try{
 //...
} catch(InterruptedException e) { 
   Thread.currentThread().interrupt(); 
}

または

try{
 //...
} catch(InterruptedException e) {
   throw new RuntimeException(e);
}

編集部:この2つはどのような場面で使われるのかも知りたいです。

解決方法は?

<ブロッククオート

InterruptedExceptionの処理方法として、以下のようなものがありますが、どのような違いがあるのでしょうか?また、最適な方法は何ですか?

を投げるメソッドを呼び出したので、この質問をすることになったのでしょう。 InterruptedException .

まず最初に throws InterruptedException ということである。メソッドシグネチャの一部であり、呼び出したメソッドがもたらす可能性のある結果です。ですから、まずは InterruptedException は、メソッド呼び出しの完全に有効な結果です。

さて、呼び出したメソッドがこのような例外をスローした場合、どうすればよいのでしょうか。 あなたの メソッドはどうするのでしょうか?次のように考えると答えが見えてきます。

メソッドに意味があるのか? あなた を投げるように実装しています。 InterruptedException ? 別の言い方をすれば InterruptedException を呼び出すと、賢明な結果が得られる。 あなたの メソッドを使用することができますか?

  • もし はい であれば throws InterruptedException の一部であるべきです。 あなたの メソッドシグネチャで、例外を伝播させる (つまり、まったくキャッチしない) 必要があります。

    : あなたのメソッドは、ネットワークからの値を待って、計算を終了して結果を返します。ブロッキング・ネットワーク・コールが InterruptedException あなたのメソッドは正常な方法で計算を終了することができません。あなたは InterruptedException を伝播させます。

    int computeSum(Server server) throws InterruptedException {
        // Any InterruptedException thrown below is propagated
        int a = server.getValueA();
        int b = server.getValueB();
        return a + b;
    }
    
    
  • もし いいえ でメソッドを宣言してはいけません。 throws InterruptedException で、例外をキャッチする必要があります(必ず!)。さて、このような状況で気をつけなければならないことが2つあります。

    1. 誰かがあなたのスレッドに割り込んできた。その人はおそらく、操作をキャンセルしたい、プログラムを優雅に終了させたい、などと思っているはずです。あなたはその誰かに礼儀正しく接し、それ以上何もせずにメソッドから戻るべきです。

    2. にもかかわらず あなたの メソッドは InterruptedException しかし、スレッドが中断されたという事実は、まだ重要な意味を持つかもしれません。特に、あなたのメソッドを呼び出すコードは、あなたのメソッドの実行中に割り込みが発生したかどうかに興味があるかもしれません。したがって、中断されたフラグを設定することによって、中断が起こったという事実を記録する必要があります。 Thread.currentThread().interrupt()

    : ユーザーは2つの値の合計を表示するように要求しています。印刷する " Failed to compute sum は、合計が計算できない場合は許容範囲内です(そして、プログラムが、(1) (2) (3) (4) (5) (6) (7) (8) (9) (10)のためにスタックトレースでクラッシュするよりはずっとましです。 InterruptedException ). 言い換えれば、それは ない でこのメソッドを宣言するのは意味がありません。 throws InterruptedException .

    void printSum(Server server) {
         try {
             int sum = computeSum(server);
             System.out.println("Sum: " + sum);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();  // set interrupt flag
             System.out.println("Failed to compute sum");
         }
    }
    
    

ここまでで明らかなように、ただ throw new RuntimeException(e) は悪い考えです。呼び出し側に対してあまり丁寧ではありません。新しい実行時例外を発明することはできますが、根本的な原因(誰かがスレッドの実行を停止させたい)がわからなくなってしまうかもしれません。

その他の例

実装について Runnable : お気づきのように Runnable.run を再投入することはできません。 InterruptedExceptions . まあね。 あなた を実装することにサインアップしました。 Runnable ということになります。 あなた に対処するために契約した。 InterruptedExceptions . など、別のインターフェイスを選択するか Callable または、上記の2番目のアプローチに従ってください。

通話 Thread.sleep : ファイルを読み込もうとしたとき、仕様では1秒間の間隔をあけて10回試行することになっています。あなたは Thread.sleep(1000) . というわけで、以下のように処理する必要があります。 InterruptedException . のようなメソッドの場合 tryToReadFile と言うのは完全に理にかなっています。 "中断されると、ファイルを読もうとするアクションを完了できない"。 . 言い換えれば、このメソッドが次のように投げることは非常に理にかなっています。 InterruptedExceptions .

String tryToReadFile(File f) throws InterruptedException {
    for (int i = 0; i < 10; i++) {
        if (f.exists())
            return readFile(f);
        Thread.sleep(1000);
    }
    return null;
}


この投稿は記事としてリライトされています こちら .