Reputation: 8358
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 Thread.isInterrupted()
, and the only difference between them is that the former resets the internal interrupted flag.
So far, I've always used Thread.isInterrupted()
and never had any problems with it. Then again, most tutorials I've seen recommend using Thread.interrupted()
. Is there any specific reason for that?
Upvotes: 66
Views: 37385
Reputation: 9446
Thread interruption in Java is advisory. If you call Thread.interrupt() then it will set the flag and cancel any outstanding IO tasks (which will throw InterruptedException). However it is up to code that is executing in the thread to handle this. Doing so is called implementing the Thread interruption policy.
However because Thread's interrupted state is shared it is important that any such handling be Thread Safe. You don't want some other thread going off and trying to do something with the interrupted flag if you are handling it. For this reason the Thread.interrupted() flag makes this atomic so it is used when you want to say: "If this thread was interrupted then I am going to deal with it). Usually this will involve cleaning up some resources. Once you are done you should probably propogate the interrupted flag so that callers can handle it. You can do this by calling Thread.interrupt again.
Upvotes: 7
Reputation: 856
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:
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:
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.
Upvotes: 2
Reputation: 1525
interrupted() method is a static method of class thread checks the current thread and clear the interruption "flag".i.e. a second call to interrupted() will return false.
isInterrupted() method is an instance method; it reports the status of the thread on which it is invoked. it does not clear the interruption flag.
If the flag is set, it will remain set after calling this method.
Thread myThread = ...;
if (myThread.interrupted()) {} //error
Thread.interrupted()//right
if (myThread.isInterrupted()) {} // Right
Upvotes: 4
Reputation: 25461
There are a lot of idioms surrounding InterruptedException
, but the question was about checking the interrupted status explicitly.
My understanding is that isInterrupted
(the instance method) should rarely be used—mainly for logging and debugging and the like. It only gives a snapshot of the flag on a given thread, which can be outdated soon afterwards.
The normal idiom is to check interrupted
(the static method) if you are writing a task which you want to be cancelable at a certain point where it is not calling something that throws InterruptedException
due to a sleep or blocking I/O call or the like. If you see the flag set, you should stop your current computation as quickly as you can, returning early or throwing an exception (perhaps InterruptedException
).
So as an example, if your task looks something like
void process(Things[] things) throws InterruptedException {
for (Thing thing : things) {
thing.twiddle(); // this call throws InterruptedException
}
}
then you do not need to do anything else; if someone calls Thread.interrupt
on your thread, during the current or next twiddle
call an InterruptedException
will be thrown up and stop your task.
But what if twiddle
does not throw InterruptedException
and generally cannot be interrupted in the middle? Say each such call takes 100ms, but things.length
might be 100. Then process
could be blocked for 10s even if someone is trying to interrupt it, which may be unacceptable in your application. So you can explicitly check for interrupts:
void process(Things[] things) {
if (Thread.interrupted()) {
return;
}
for (Thing thing : things) {
thing.twiddle();
}
}
Here you can see why it is important that interrupted
atomically checks and clears the flag: you are using it to acknowledge receipt of a message, that someone has politely requested you stop as soon as possible. (In this case, within about 100ms of the request.) You can also see why this must be a static method, operating on the current thread: it only makes sense in the context of checking whether the surrounding code should be stopped.
Of course if the caller of process
is assuming it ran to completion, simply return
ing as shown here would be misleading. So you might want to make process
return the number of things it finished processing, or it might just be more appropriate to throw the exception up:
void process(Things[] things) throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
for (Thing thing : things) {
thing.twiddle();
}
}
In this case the caller gets a (checked) exception informing them that someone else asked to stop processing in the middle. Usually the caller should just let the exception be thrown up the call stack.
You could also reinterrupt yourself if you were unable to stop your current task yet needed to know that a request to stop it did come in, for example to cut the rest of the work short:
void process(Things[] things) {
boolean twiddleFully = true;
if (twiddleFully && Thread.interrupted()) {
twiddleFully = false;
Thread.currentThread().interrupt();
}
for (Thing thing : things) {
thing.twiddle(twiddleFully);
}
}
Here we can process the remaining things more quickly but still complete the loop, and turn the interrupted flag back on so that our caller can decide to handle it.
Upvotes: 8
Reputation: 7836
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.
Upvotes: 1
Reputation: 22292
Here are a couple of examples of how you might use these methods:
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.
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.
Upvotes: 4
Reputation: 269697
The interrupted()
method is a class method that always checks the current thread and clears the interruption "flag". In other words, a second call to interrupted()
will return false
.
The isInterrupted()
method is an instance method; it reports the status of the thread on which it is invoked. Also, it does not clear the interruption flag. If the flag is set, it will remain set after calling this method.
Upvotes: 7
Reputation: 191945
interrupted()
is static
and checks the current thread. isInterrupted()
is an instance method which checks the Thread
object that it is called on.
A common error is to call a static method on an instance.
Thread myThread = ...;
if (myThread.interrupted()) {} // WRONG! This might not be checking myThread.
if (myThread.isInterrupted()) {} // Right!
Another difference is that interrupted()
also clears the status of the current thread. In other words, 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
.
The Javadocs tell you important things like this; use them often!
Upvotes: 103
Reputation: 59993
If you use interrupted
, what you're asking is "Have I been interrupted since the last time I asked?"
isInterrupted
tells you whether the thread you call it on is currently interrupted.
Upvotes: 38