2

If I write a code as below, we can not interrupt or terminate the thread. Also it will not throw InterruptedException.

Thread loop = new Thread(
  new Runnable() {
    @Override
    public void run() {
      while (true) {
      }
    }
  }
);
loop.start();
loop.interrupt();

To interrupt this thread, I need to modify my code as below:

Thread loop = new Thread(
  new Runnable() {
    @Override
    public void run() {
      while (true) {
        if (Thread.interrupted()) {
          break;
        }
        // Continue to do nothing
      }
    }
  }
);
loop.start();
loop.interrupt();

My Question is,

  1. why Java is designed in such way that InterruptedException is being thrown only in case of blocking methods like sleep() and wait().

  2. Why in normal code, we need to handle this manually as in my above code snippet? Why Java is not throwing InterruptedException whenever we set interrupted flag true through interrupt() method?

I have read so many blogs and articles on InterruptedException, but haven't find any convincing answer.

Edit

found good article on InterruptedException : http://codepumpkin.com/interruptedexception-java-multithreading/

Abhi Andhariya
  • 550
  • 5
  • 15
  • 6
    If code could be interrupted during normal execution, it would have to make the check between every line of code, and would be very slow. Also, some code requires that it run to completion, otherwise it would produce unpredictable bugs (such as not closing a resource). – 4castle May 06 '17 at 17:24
  • 1
    That's basically what the deprecated stop() method did. You can read the reason why it's been deprecated in its javadoc. But 4castle explained it very well. – JB Nizet May 06 '17 at 17:26
  • 1
    Java interruption is *cooperative*. One thread can ask another to stop what it is doing, but there is no requirement for the other thread to act on that, either immediately or even ever. – Andy Turner May 06 '17 at 17:27
  • 1
    @4castle : nicely explained. Thanks. – Abhi Andhariya May 06 '17 at 17:35
  • 1
    @JB Nizet: sure. I will read javadoc for stop() – Abhi Andhariya May 06 '17 at 17:36
  • 2
    @4castle: Also found below lines at http://www.yegor256.com/2015/10/20/interrupted-exception.html The code should either be bullet-fast or interruption-ready, nothing in between. If your code is fast, you never check the interruption flag, because you don't want to deal with any interruptions. If your code is slow and may take seconds to execute, make it explicit and handle interruptions somehow. That's why InterruptedException is a checked exception. Its design tells you that if you want to pause for a few milliseconds, make your code interruption-ready. – Abhi Andhariya May 06 '17 at 17:40

2 Answers2

6

1) why Java is designed in such way that InterruptedException is being thrown only in case of blocking methods like sleep() and wait().

The whole point of thread.interrupt() is that it is cooperative. A thread is interrupted but it has to check for the interrupt flag using Thread.currentThread().isInterrupted() so it can manage it's own termination properly and clean up the shared objects, locks, finally blocks, etc. if necessary.

To quote from the tutorial on the subject, emphasis mine.

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.

The methods that do throw InterruptedException are the ones that are waiting on locks and other conditions. These throw the exception when they are interrupted so again the thread can clean itself up before terminating.

2) Why in normal code, we need to handle this manually as in my above code snippet? Why Java is not throwing InterruptedException whenever we set interrupted flag true through interrupt() method?

The alternative would have been to have InterruptedException be a RuntimeException which could have been thrown at any time regardless of whether or not the program was anticipating it. Part of the problem with stop() and the other deprecated Thread methods was that they tended to violate various language constructs and could possibly leave the application memory in a bad state. Here's more details about that.

The same could be said for InterruptedException if it was a RuntimeException. You can imagine if a thread was altering a shared object and then just midstream threw a unexpected RuntimeException or was stopped altogether. The shared object being updated could easily be left in a invalid state.

if (Thread.interrupted()) {

This is not the right method to call because it clears the interrupt flag on the thread which is a bad pattern. Please use the following:

if (Thread.currentThread().isInterrupted()) {

This preserves the interrupt flag which should be done if possible. Also, when InterruptedException is thrown that also clears the interrupt flag. That's why it's a good pattern to do:

try {
   ...
} catch (InterruptedException ie) {
   // re-interrupt the thread to propagate the interrupt flag
   Thread.currentThread().interrupt();
   // handle the interrupt here by probably quitting the thread
}

There are many problems where libraries "swallow" the interrupt flag. Even if your code is small it may get copied into a larger block so you always way to restore the interrupt flag as a good pattern.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • 1
    Thanks Gray.. understood..!! – Abhi Andhariya May 06 '17 at 18:59
  • 1
    Re: "Also, when you catch `InterruptedException` that also clears the interrupt flag": That's not quite right. Rather, it's just that the JDK methods that *throw* `InterruptedException` all clear the interrupt flag before doing so. But if the flag is set, for whatever reason, when you catch `InterruptedException`, then the mere act of catching that exception won't clear the flag. See e.g. http://ideone.com/H4wzrA. (But your suggested pattern is nonetheless the right one.) – ruakh May 08 '17 at 05:31
  • My only wish is that there was a 'star' for answers so I could not just up vote this as a good answer but flag it as a great answer. – Persixty Jul 06 '17 at 00:59
  • d= (◕‿↼ ) Thanks! **see also** stackoverflow.com/[How to ignore InterruptedException?](https://stackoverflow.com/a/28544993/8740349) – Top-Master Jun 01 '22 at 19:04
1

Early versions of Java used to be able to kill threads, but that quickly became a problem when trying to support multiple operating systems. There are very different methods Operating Systems implement threading with very different capabilities. Stopping a thread mid-flight was deemed unsafe that could lead to unexpected behavior in other parts of the application, like deadlocks.

More details here: https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

Jochen Bedersdorfer
  • 4,093
  • 24
  • 26
  • 2
    Thanks for throwing lights on deprecation of stop() method and killing threads. But its not about stopping the thread, its just about interrupting the child thread from owner thread. We can always take preventive actions to handle unexpected behaviours. What i found more convincing is 4castle's comment above : "If code could be interrupted during normal execution, it would have to make the check between every line of code, and would be very slow." Any way thanks. Upvoting your answer :) – Abhi Andhariya May 06 '17 at 17:51
  • *"We can always preventive actions to handle unexpected behaviours."* .. Oh really? Tell me, how would you maintain failure atomicity if you can't know exactly when (or where) a thread is going to end? – scottb May 06 '17 at 17:57
  • 1
    there's compiled code that your thread is currently running. Unless the OS decides to give a slice of CPU time to another thread, there's no way your code can be interrupted at any moment. So instead of relying on the OS making this happen behind the scenes, the burden is on the developer to let the thread be interrupted at a convenient time. This is a compromise as Java code is able to run on many different architectures with wildly varying capabilities with regards to threading. – Jochen Bedersdorfer May 06 '17 at 18:11