Java: Difference in usage between Thread.interrupted() and Thread.isInterrupted()?

后端 未结 9 687
南旧
南旧 2020-12-12 16:28

Java question: As far as I know, there are two ways to check inside a thread whether the thread received an interrupt signal, Thread.interrupted() and Thr

相关标签:
9条回答
  • 2020-12-12 16:59

    Here are a couple of examples of how you might use these methods:

    1. If you were writing your own thread pool, you might want to check the interrupted status on one of the threads that you are managing. In that case, you would call managedThread.isInterrupted() to check it's interrupted status.

    2. If you are writing your own InterruptedException handlers that don't immediately retrigger an equivalent exception via Thread.currentThread().interrupt() (for example, you might have a finally block after your exception handlers), you might want to check whether that thread that you are currently running on has been interrupted via an outside call or InterruptedException. In that case, you would check the boolean value of Thread.interrupted() to check on the status of your current thread.

    The second method is really only ever useful to me in situations where I'm afraid that someone has written an exception eater at a lower level that, by extension, has eaten an InterruptedException as well.

    0 讨论(0)
  • 2020-12-12 17:04

    This is a old question and having gone through the answers I feel that there is still some missing information. Here's my attempt to fill in that missing piece of info.

    From Java 5 onwards usually you would deal with Threads only indirectly .Infact threads spawned from the java.util.Executor framework are dealt within library methods. These threads often call entities that are of blocking nature like Future.get() . ie get() blocks untill result is available .Now there is a overloaded form of get() that takes a timeout value and calling that method means that the thread wants to wait for a period equal to the timeout for the get () to return a value ,if not that task can be cancelled via Future.cancel(). So these methods deal with interruption seriously in that as soon as they sniff a interruption , they also throw the checked InterruptionException . Hence the callers are forced to handle InterruptionException. Since they already propagate the InterruptedException which conveys the interrupted status , it makes sense for the blocking mehthods to also clear the interrupted status by calling Thread.interrupt(). Otherwise , the contract of InterruptedException is violated.

    However , if you are dealing with raw threads which is ofcourse not recommnended now , you should be careful when calling the static method interrupted() because if you call it twice in a row and the thread is not interrupted between the two calls, the second call will return false even if the first call returned true.

    0 讨论(0)
  • 2020-12-12 17:04

    Why interrupt?

    Interrupting threads in Java is useful when you have a long running task that you now need to stop, or when you have a daemon that you need to turn off, and other examples.

    How to interrupt

    To interrupt you call interrupt() on the thread. This is a cooperative process, so your code has to be ready for it. Like this:

    myThread.interrupt();
    

    Responsible code

    Your code's responsibility is to be ready for any interruptions. I'd go so far to say that whenever you have a long running task, that you insert some interrupt ready code like this:

    while (... something long...) {
    
         ... do something long
    
         if (Thread.interrupted()) {
             ... stop doing what I'm doing...
         }
    }
    

    How to stop what I'm doing?

    You have several options:

    1. If your you are in Runnable.run() just return or break out of the loop and finish the method.
    2. You may be in some other method deep in the code. It may make sense at that point for that method to throw InterruptedException so you would just do that (leaving the flag cleared).
    3. But maybe deep in your code it doesn't make sense to throw InterruptedException. In that case you should throw some other exception, but before that mark your thread interrupted again so the code that catches knows that an interrupt was in progress. Here's an example:
    private void someMethodDeepDown() {
        while (.. long running task .. ) {
              ... do lots of work ...
    
              if (Thread.interrupted()) {
                 // oh no! an interrupt!
                 Thread.currentThread().interrupt();
                 throw new SomeOtherException();
              }
         }
    }
    

    Now the exception can propagate an either terminate the thread or be caught, but the receiving code hopefully notices that an interrupt is in progress.

    Should I use isInterrupted() or interrupted()

    You should prefer interrupted() because:

    1. Your code should reset the interrupt flag because if you don't the thread you are using could go back to a thread pool with an interrupted state causing problems (of course, that's a bug in the thread pool code, you won't get that behavior if you use Executors.newFixedThreadPool() for example. But other threading code could have it.
    2. As another answer stated, the clearing of the interrupted flag indicates that you've received the message and are taking action. If you leave it on true, the after a while caller can assume you won't respond to it in a timely manner.

    Why interrupt() why not some other flag in my code?

    Interrupt is the best mechanism for interruption because our code can be ready for it. If we find code that is just catching and ignoring the InterruptExceptions or not checking for interrupted() in its body then we can correct those mistakes and make our code always cleanly interruptible without creating arcane dependencies on non-standard mechanisms in your code.

    Unfortunately Joshua Block proposed the opposite in his famous book Effective Java, Second Edition. But I believe enabling the interrupt() method to work as intended is much better.

    Doesn't Future.cancel() already handle this?

    Future cancel removes the task from the running queue. If your task is already running it won't stop it. So cancel() is a different concept that interrupting. As the Javadocs say:

    Attempts to cancel execution of this task. This attempt will fail if the task has already completed, has already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task. https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/Future.html#cancel(boolean)

    But calling it will generate an interrupt if mayInterruptIfRunning is on.

    0 讨论(0)
提交回复
热议问题