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

前端 未结 4 1434
我寻月下人不归
我寻月下人不归 2020-12-11 08:47

I have a thread in Java which calls

t.interrupt();

making t (a different thread) be interrupted. I want the \"t\" thread to then catch an

相关标签:
4条回答
  • 2020-12-11 09:47

    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

    0 讨论(0)
  • 2020-12-11 09:51

    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().

    0 讨论(0)
  • 2020-12-11 09:51

    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.

    0 讨论(0)
  • 2020-12-11 09:54

    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. 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:

    • What does java.lang.Thread.interrupt() do?
    • How exactly does Thread.interrupt() and Thread.interrupted() work?
    • How to stop uninterruptible threads in Java
    0 讨论(0)
提交回复
热议问题