Why is swallowing InterruptedException ok for Thread subclasses?

In Brian Goetz's article on how to handle an InterruptedException , one paragraph stands out:

The only thing acceptable for swallowing an interrupt is when you know that the thread is about to exit. This scenario only occurs when the class invoking the intermittent method is part of Thread, not Runnable.

I do not understand. Is the reason that something related to Runnable possibly handled by threadpool, while Thread is what you start on your own?

+4
source share
3 answers

Basically. The concern expressed in this article is that if you swallow the interupt exception, then calling the code above on the stack will not know about overloading, which can cause unwanted behavior. If you start a thread, then you know that there is nothing of a higher level in the call stack that takes care of being mixed up, this thread will not continue to live in the thread pool, so just let go of the thread.

I hate InterruptedException, I think it gives checked exceptions a bad name, and this article does not change this perspective. If it was so important that this exception went to the call stack, Runnable.run () should have declared it in the method declaration so that you could just throw it, or it should have been an unchecked exception for the same reason. SecurityException - Uncontrolled exception.

My preferred design would be that the methods return a boolean if they were interrupted, if you want to know, but this article concludes that this will not necessarily be practical.

+4
source

I would say that the Thread extension was unnecessary, and therefore a Runnable implementation is preferred.

But the important thing is that the code knows that the thread is about to exit. If your code is part of some kind of common callback interface, you may not know how you are using. You can be transferred to a thread pool (indeed, we should probably use pools, not build Thread at inappropriate points in the code). OTOH, usually Runnable is an anonymous inner class, and therefore, at the source level, is part of an inline method that knows what is going on.

So, if the thread is about to exit, resetting the interrupt state in the current thread is pointless because there is nothing to interrupt.

At some point you will want to say that he interrupted enough. Thread pools, for example, may continue to use the thread even after the task has been interrupted, although they may want to save InterruptException for callers who try to complete the task.

Libraries usually do not handle interrupts correctly. IMO, interrupts have no context to make sense. Without them, life will be much simpler, unfortunately, they feel their presence.

+3
source

I agree with the rest that the difference is whether you control this stream or not. If you extended Thread, it pretty much means that you are in control of this thread. On the other hand, if your code is just Runnable, it can be run on a borrowed thread (for example, from a thread pool) that you do not have. Eating an exception and not restoring the interrupt status, you deprive the code above of the ability to recognize and act upon the interrupt.

InterruptedException, being a checked exception, I find good. InterruptedException - a way to request cancellation of tasks. Suppose you write a task as Runnable, which includes a locking method that throws an InterruptedException. If this was not a checked exception, if you are not careful, you can not think about breaking an InterruptedException (thus, canceling it) and do your own cleaning .

 public class MyTask implements Runnable { public void run() { while (someCondition) { Object value = someBlockingQueue.take(); // act on the value and loop back } } } 

Since InterruptedException is a checked exception, how my task should respond to interruption (cancellation) is the front and the center.

 public class MyTask implements Runnable { public void run() { while (someCondition) { try { Object value = someBlockingQueue.take(); // act on the value and loop back } catch (InterruptedException e) { // I'm being cancelled; abort cleanUp(); // restore the interrupt Thread.currentThread().interrupt(); break; } } } } 
+2
source

All Articles