6

私はマルチスレッドアプリケーションを開発して、外部サーバー(それぞれが別々のスレッド上にある)に接続し、入力があるまでブロックされます。これらはそれぞれ、Threadクラスを拡張します。説明のために、これらを「接続スレッド」と呼びましょう。

これらの接続スレッドはすべて、同時ハッシュマップに格納されます。

次に、RESTfulWebサービスのメソッド呼び出しでスレッドをキャンセルできるようにします。(私はGrizzly / Jerseyを使用しているので、各呼び出しはそれ自体がスレッドです。)

(ハッシュマップから)特定の接続スレッドを取得し、その上でinterrupt()メソッドを呼び出します。

それで、ここに、接続スレッド内で、InterruptedExceptionをキャッチする方法についての質問がありますか?(接続スレッドが外部のRESTfulコマンドによって停止されたときに何かをしたいのですが。)

4

5 に答える 5

10

それで、ここに、接続スレッド内で、InterruptedExceptionをキャッチする方法についての質問がありますか?

それはいけません。読み取りI/O操作でスレッドがブロックされている場合は、ブロックできませんinterrupted。これはinterrupt、スレッドが中断されたことを示すフラグを設定するだけだからです。ただし、スレッドがI / Oでブロックされている場合、フラグは表示されません。
このための適切な方法は、基になるソケット(スレッドがブロックされている)を閉じてから、例外をキャッチして伝播することです。
したがって、接続スレッドextend Threadは次のこと を行います。

@Override  
public void interrupt(){  
   try{  
      socket.close();  
   }  
   finally{  
     super.interrupt();  
   }  
}   

このようにして、I/Oでブロックされたスレッドを中断することができます。

次に、あなたのrun方法で:

@Override  
public void run(){  

    while(!Thread.currentThread().isInterrupted()){    
       //Do your work

    }  
}    

catchしたがって、あなたの場合は、しようとしないでくださいInterruptedException。I/Oでブロックされたスレッドを中断することはできません。スレッドが中断されているかどうかを確認し、ストリームを閉じて中断を容易にします。

于 2012-09-01T19:28:46.760 に答える
2

ブロッキングの問題です。

ホバーラー、このコードを試してみてください、多分それはあなたを助けるでしょう:

try{
 yourObject.read();
}catch(InterruptedException ie){
// interrupted by other thread
}
catch(Exception ex){
// io or some other exception happent
}

あなたのreadメソッドは、ソケットに利用可能なバイトがあるかどうかをチェックする必要があります。たとえば、それを読むよりもある場合は、speelモードに移動します。使用可能なよりもスリープしている場合、purソケット読み取り(読み取りが何であれ)でのウェイクアップ(InterruptedException)はブロックされます。一部のAPIには、次のコードが実行される以外に何も読み取られない場合、最大待機値、たとえば5秒60秒の値があります。

class MyReadingObject
{
   public read() throws InterruptedException{
      while(shouldIread){
        if(socket.available() > 0){
           byte[] buff = new byte[socket.avaialble()]
           socket.read(buff);
           return;
        }
        else{
           Thread.currentThread.sleep(whateverMilliseconds);
        } 
     }
  }
}

そのようなものですが、エラー処理といくつかのデザインパターンがあります

于 2012-09-01T19:24:29.307 に答える
2

あるスレッドを呼び出すとThread.interrupt()、そのスレッドに「割り込み」フラグが設定されます。Thread.interrupted()一部のメソッドはこのフラグを(またはによって)チェックしてThread.isInterrupted()スローInterruptedExceptionしますが、通常はブロックできるメソッドのみがそれを行います。したがってInterruptedException、中断されたスレッドでスローされる保証はありません。をスローするメソッドを呼び出さない場合InterruptedException、例外はまったくスローされないため、その例外をキャッチしても意味がありません。ただし、を呼び出すことで、スレッドが中断されたかどうかをいつでも確認できますThread.isInterrupted()

于 2012-09-01T19:28:37.477 に答える
1

interrupt()スレッドを呼び出しても停止するのではなく、割り込みフラグをオンにするだけです。スレッドの割り込みステータスの変更を考慮して処理し、それに応じて動作するのはコードの責任です。そのスレッドでブロッキング操作を実行している場合、スレッドが読み取りで「ブロッキング」しているため、ほぼSOLになります。私がここに投稿した答えを見てください。したがって、基本的に、ループを繰り返したり、そのスレッド内のいくつかのフラグを定期的にチェックしたりしない限り、ソケットなどを閉じずにブレークアウトする方法はありません。

ここでの1つの解決策は、基になる接続オブジェクトを「明示的に」公開して呼び出しclose()、ある種の例外をスローするように強制することです。これは、スレッド化されたコードで処理できます。何かのようなもの:

class MyAction extends Thread implements Disposable {

  public void doStuff() {
    try {
      byte[] data = this.connection.readFully();
  } catch (InterruptedException e) {
    // possibly interrupted by forceful connection close    
  }

  @Override
  public void dispose() {
    this.connection.close();
  }
}

// Elsewhere in code
MyAction action = conMap.get("something");
action.dispose();
于 2012-09-01T19:29:53.890 に答える
-2

次のようなtry-catchを使用します。

try {
    //code
} catch ( InterruptedException e) {
    //interrupted
}

これでうまくいくと思います。終了するかどうかについてブール変数を保持することもできるので、その変数をチェックします。それがtrueの場合は、停止します。

于 2012-09-01T19:24:42.040 に答える