adeady
adeady

Reputation: 23

Thread not throwing an InterruptedException when interrupt() is called

I am working on an application that reads and processes data over a network. While testing the connecting/disconnecting logic of the program I noticed that my consumer thread was not closing when it reached it's closing condition. Below is a stripped out version of the consumer class.

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());
   }
}

I created a dummy main class that demonstrates the problem.

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");
      }
   }
}

When you run this code as written, the consumer detects the interrupt, but does not stop execution until the pipe is empty (not what I want). Just to try, I changed to a Thread.stop() call which did what I wanted, but I don't want to leave that in production code. I realized that I could use a simple return statement, but this is not the only point the thread could exit, and I'd like to have some common exit code that cleans up resources. So, my question is, why is the consumer thread not being interrupted? and is there a good way for me to be able to have common exit code?

Thanks!

Upvotes: 2

Views: 4254

Answers (3)

Siddharth Tyagi
Siddharth Tyagi

Reputation: 92

You could simply use break to label

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);
        }
     }

Upvotes: 0

Elliott Hill
Elliott Hill

Reputation: 961

InterruptedExceptions are thrown when a thread is sleeping, waiting for a join etc. (basically any interruptable blocking call) and interrupt() is called.

If you thread is running then the thread interrupt flag will be set but no exception will be thrown, you should check the flag with myThread.isInterrupted().

You can find more information here: http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html

Upvotes: 9

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 341003

Which method do you expect to throw InterruptedException? Thread.interrupt() is not throwing it, neither any of your methods. So where do you expect this checked exception should come from?

Your code is not working because interrupt() barely sets the interrupted flag on a thread. You must check that flag explicitly using Thread.isInterrupted(). InterruptedException is only thrown if the thread in question was sleeping or blocking at the time. So if you interrupt different thread and that thread was sleeping, sleep() will throw InterruptedException.

Now to address your problem in detail. Exceptions are for exceptional cases. The fact your thread finished processing is not exceptional case, it's something you definitely expect. For the same reason reading a file past the end is not throwing an exception - end of file is something you should definitely expect - all files have end. Moreover you should not use exceptions to control program flow.

In your case either use return statement (when run() returns, thread dies) or break your loop in some other way. You posted too much code to analyze.

Upvotes: 2

Related Questions