1

私は、ネットワークを介してデータを読み取って処理するアプリケーションに取り組んでいます。プログラムの接続/切断ロジックをテストしているときに、コンシューマースレッドがクローズ状態に達したときにクローズしていないことに気付きました。以下は、コンシューマークラスの簡略版です。

import java.io.InputStream;

public class Consumer implements Runnable
{
   private final InputStream input;
   public Consumer(InputStream input)
   {
      this.input = input;
   }
   @Override
   public void run()
   {      
      byte readBuffer[];
      readBuffer = new byte[1];
      int goodData;

      try
      {
         while(input.available() > 0)
         {
            goodData = input.read(readBuffer);
            while (goodData > 0 )
            {
               System.out.println(readBuffer[0]);
               if ( readBuffer[0] == 27 )
               {
                  System.out.println("Consumer: found closing byte and closing thread "+Thread.currentThread().getName());
                  //this is the last packet, so interupt thread to close
              Thread.currentThread().interrupt();
              //return;
              //Thread.currentThread().stop(new InterruptedException("Attempting to close"));
               }
               goodData = input.read(readBuffer);
            }
         }
      }
      catch(Exception e)
      {
         System.out.println("closing "+Thread.currentThread().getName() +" because of an exception "+e.getClass());
         return;
      }
      System.out.println("closing "+Thread.currentThread().getName());
   }
}

問題を示すダミーのメインクラスを作成しました。

public class ExampleOfInterruptNotWorking
{
   public static void main(String[] args)
   {
      byte[] bytesToWrite = new byte[]{0, 1, 2,3,4,5,6,65,23,65,21,54,13,54,1,76};
      Consumer C;
      Thread ConsumerThread;
      PipedInputStream PIS = null;
      PipedOutputStream POS = null;
      try
      {
         PIS = new PipedInputStream();
         POS = new PipedOutputStream(PIS);
         C = new Consumer(PIS);
         ConsumerThread = new Thread(C);

         ConsumerThread.start();

         POS.write(bytesToWrite);
         POS.write(bytesToWrite);
         bytesToWrite[1] = 27;
         POS.write(bytesToWrite);

         ConsumerThread.join();

      }
      catch(Exception e)
      {
         System.err.println("Unexpected exception in main");
         e.printStackTrace(System.err);
      }
      finally
      {
         try
         {
            PIS.close();
            POS.close();
         }
         catch(Exception ex)
         {
        //shouldn't happen in example
         }
         System.out.println("exiting main");
      }
   }
}

このコードを記述どおりに実行すると、コンシューマーは割り込みを検出しますが、パイプが空になるまで実行を停止しません(私が望むものではありません)。試してみるために、私はThread.stop()呼び出しに変更しました。これは私が望むことを実行しましたが、それを本番コードに残したくありません。単純なreturnステートメントを使用できることに気付きましたが、スレッドが終了できるのはこれだけではありません。リソースをクリーンアップする一般的な終了コードが必要です。だから、私の質問は、なぜコンシューマースレッドが中断されないのですか?共通の終了コードを使用できるようにするための良い方法はありますか?

ありがとう!

4

3 に答える 3

9

InterruptedExceptionsは、スレッドがスリープしているとき、参加を待っているときなど(基本的には割り込み可能なブロッキング呼び出し)にスローされ、interrupt()が呼び出されます。

スレッドが実行されている場合、スレッド割り込みフラグが設定されますが、例外はスローされません。フラグをで確認する必要がありますmyThread.isInterrupted()

詳細については、 http: //www.ibm.com/developerworks/java/library/j-jtp05236/index.htmlを参照してください。

于 2012-08-16T12:04:07.100 に答える
2

どの方法を投げると思いますInterruptedExceptionか?Thread.interrupt()それを投げていません、あなたの方法もありません。では、このチェックされた例外はどこから来ると思いますか?

スレッドにフラグをinterrupt()ほとんど設定しないため、コードは機能していません。interruptedを使用して、そのフラグを明示的にチェックする必要がありThread.isInterrupted()ます。InterruptedException問題のスレッドがその時点でスリープまたはブロックしていた場合にのみスローされます。したがって、別のスレッドを中断し、そのスレッドがスリープしていた場合、sleep()はスローされInterruptedExceptionます。

次に、問題に詳細に対処します。例外は例外的な場合です。あなたのスレッドが処理を終えたという事実は例外的なケースではありません、それはあなたが間違いなく期待するものです。同じ理由で、ファイルの終わりを超えて読み取ることは例外をスローしません-ファイルの終わりは間違いなく期待すべきものです-すべてのファイルには終わりがあります。さらに、プログラムフローを制御するために例外を使用しないでください。

あなたの場合、returnステートメントを使用するか(returnの場合run()、スレッドが終了します)、または他の方法でループを中断します。投稿したコードが多すぎて分析できません。

于 2012-08-16T12:02:28.290 に答える
0

単にブレークを使用してラベルを付けることができます

OUTER:
     while(input.available() > 0)
     {
        goodData = input.read(readBuffer);
        while (goodData > 0 )
        {
           System.out.println(readBuffer[0]);
           if ( readBuffer[0] == 27 )
           {
              System.out.println("Consumer: found closing byte and closing thread "+Thread.currentThread().getName());
              //this is the last packet, so interupt thread to close
          //Thread.currentThread().interrupt();
          break OUTER;
          //return;
          //Thread.currentThread().stop(new InterruptedException("Attempting to close"));
           }
           goodData = input.read(readBuffer);
        }
     }
于 2012-08-17T09:51:01.347 に答える