I want my thread to handle interruption, but I can't catch InterruptedException because it is a checked exception

耗尽温柔 提交于 2019-11-28 12:51:42

While the other answers are correct, a fuller explanation is appropriate.

A thread can be safely interrupted (in the general sense of the word) only at specific points in its execution. In particular, it can be interrupted safely when it has issued a wait() call, or has invoked a service that can issue wait(). This is why InterruptedException is a checked exception and not a runtime (unchecked) exception. Allowing a thread to be arbitrarily interrupted at any point would make execution non-deterministic (at least that's the way the JVM was specified). There is a Thread#stop() method which is strongly deprecated because it causes more problems than it solves. From the Javadoc

This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait. For more information, see Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?.

If you need to interrupt a running thread, then you must periodically poll the interrupted status with Thread.interrupted() or .isInterrupted() or poll a shared variable, and take appropriate action yourself.

Note: The term "interrupted" above (except as part of a method name) is intended in the general sense, not the specific meaning of calling Thread#interrupt().

Gray

I really don't like the accepted answer so I thought I'd throw my $0.02 in.

I want the "t" thread to then catch an InterruptedException but Eclipse won't let me put an InterruptedException in saying it's not thrown in the try body. How can I get the InterruptedException to be called? Am I using t.interrupt() wrong?

It is important to realize that t.interrupt() only sets the interrupted bit in a thread -- it doesn't actually interrupt the thread's processing per se. A thread can be interrupted at any time safely.

To quote from the Thread.interrupt() javadocs:

  • If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

  • If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a java.nio.channels.ClosedByInterruptException.

  • If this thread is blocked in a java.nio.channels.Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.

  • If none of the previous conditions hold then this thread's interrupt status will be set.

It is important to add that if the thread's interrupt bit has been set and then wait() (and others) is called, then the wait() will throw InterruptedException immediately.

So you can't catch InterruptedExeption everywhere since only certain methods throw it. As others have mentioned, if you want to see if a thread has been interrupted (again has the interrupt bit set) then the right thing to do is to test for it directly with the Thread.getCurrentThread().isInterrupted(). Typically we do something like the following:

while (!Thread.getCurrentThread().isInterrupted()) {
     // process stuff
     ...
     try {
         // here's an example of a method that throws InterruptedException
         Thread.sleep(100);
     } catch (InterruptedException e) {
         // catching InterruptedException actually clears the interrupt bit
         // so it is a good pattern to re-interrupt the thread immediately
         Thread.currentThread().interrupt();
         // now we decide what to do since we are interrupted
         break;
     }
}

There are a number of good questions and answers on this topic:

Rather than catching InterruptedException you can call Thread.interrupted() or Thread.getCurrentThread().isInterrupted() (the former will clear the interrupted flag, the latter will not), which will return true if the interrupted flag is set. You can only catch InterruptedException if you've called a method that throws it, like sleep

InterruptedException is only thrown from specific method calls - mostly any method calls that wait, sleep or do I/O, so it wont be thrown out of anywhere.

if the Thread youre trying to interrupt is doing something CPU-internsive and not I/O, you will need to sprinkle Thread.getCurrentThread().isInterrupted() calls in there otherwise the target thread might never notice.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!