I'm reading this book, (O'Reillys Java Threads 3rd ed., which for now has very bad explanations), and I have encountered this code:
//in RandomCharacterGenerator class
public void run( ) {
while (!isInterrupted()) {
nextCharacter( );
try {
Thread.sleep(getPauseTime( ));
} catch (InterruptedException ie) {
return;
}
}
}
And the following explanation (producer is the instance of upper class in the main thread):
producer.interrupt( );
If the main thread executes this statement while the RandomCharacterGenerator thread is sleeping, the RandomCharacterGenerator thread gets the interrupted exception and immediately returns from the run() method. Otherwise, when the character-feeding thread next gets to the top of its loop, it sees that the interrupted flag has been set and returns from its run() method then. Either way, the random character generator thread completes its task.
Note that this technique does not completely eliminate the possibility that we sleep for some amount of time after the thread is asked to stop. It's possible for the main thread to call the interrupt() method just after the RandomCharacterGenerator has called the isInterrupted() method. The character-reading thread still executes the sleep() method, which won't be interrupted (since the main thread has already completed the interrupt() method). This is another example of a race condition that we solve in the next chapter. Since the race condition in this case is benign (it just means we sleep one more time than we'd like), this is sufficient for our purposes.
Second paragraph is completely unclear to me. My first question is: How can we sleep one more cycle? If we interrupt the thread when sleeping it goes out of run, if we interrupt before sleep it will interrupt sleep as soon as it starts sleeping (I tested that, and I think that's true? Am I right), if we interrupt after sleep it will brake the loop.
Second question: In this example (this is the whole code from the book) is the check in loop completely unnecessary, and can it stand while (true) with the same outcome, so that first paragraph about the top of the loop is complete nonsense?
The book is wrong. Interrupting the thread before it sleeps will make the sleep() method throw an InterruptedException immediately.
Quote from Java Concurrency in Practice:
A good way to think about interruption is that it does not actually interrupt a running thread; it just requests that the thread interrupt itself at the next convenient opportunity. (These opportunities are called cancellation points.) Some methods, such as wait, sleep, and join, take such requests seriously, throwing an exception when they receive an interrupt request or encounter an already set interrupt status upon entry.
(emphasis mine)
In this particular example, using while(true) would lead to the same effect. But in other cases, if the loop never calls an interruptible method, or if you want to exit as soon as possible, you'll have to regularly check if the thread is interrupted to be able to detect the interruption.
The book believes you will spend an extra cycle in the following case:
RandomCharacterGenerator -> isInterrupted = false;
Main -> interrupt()
RandomCharacterGenerator -> runs through code
RandomCharacterGenerator -> sleeps
RandomCharacterGenerator -> isInterrupted = true
It actually will interrupt on the sleep, but the thing it is trying to get at that is important is that you may run through the code one more time after calling interrupt()
Related
I have read that we should always call a wait() from within a loop:
while (!condition) { obj.wait(); }
It works fine without a loop so why is that?
You need not only to loop it but check your condition in the loop. Java does not guarantee that your thread will be woken up only by a notify()/notifyAll() call or the right notify()/notifyAll() call at all. Because of this property the loop-less version might work on your development environment and fail on the production environment unexpectedly.
For example, you are waiting for something:
synchronized (theObjectYouAreWaitingOn) {
while (!carryOn) {
theObjectYouAreWaitingOn.wait();
}
}
An evil thread comes along and:
theObjectYouAreWaitingOn.notifyAll();
If the evil thread does not/can not mess with the carryOn you just continue to wait for the proper client.
Edit: Added some more samples.
The wait can be interrupted. It throws InterruptedException and you might need to wrap the wait in a try-catch. Depending on your business needs, you can exit or suppress the exception and continue waiting.
It's answered in documentation for Object.wait(long milis)
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
(For more information on this topic,
see Section 3.2.3 in Doug Lea's
"Concurrent Programming in Java
(Second Edition)" (Addison-Wesley,
2000), or Item 50 in Joshua Bloch's
"Effective Java Programming Language
Guide" (Addison-Wesley, 2001).
Why should wait() always be called inside a loop
The primary reason why while loops are so important is race conditions between threads. Certainly spurious wakeups are real and for certain architectures they are common, but race conditions are a much more likely reason for the while loop.
For example:
synchronized (queue) {
// this needs to be while
while (queue.isEmpty()) {
queue.wait();
}
queue.remove();
}
With the above code, there may be 2 consumer threads. When the producer locks the queue to add to it, consumer #1 may be blocked at the synchronized lock while consumer #2 is waiting on the queue. When the item is added to the queue and notify called by the producer, #2 is moved from the wait queue to be blocked on the queue lock, but it will be behind the #1 consumer which was already blocked on the lock. This means that the #1 consumer gets to go forward first to call remove() from the queue. If the while loop is just an if, then when consumer #2 gets the lock after #1 and calls remove(), an exception would occur because the queue is now empty -- the other consumer thread already removed the item. Even though it was notified, it needs to be make sure the queue is for sure not empty because of this race condition.
This well documented. Here's a web page I created a while back which explains the race condition in detail and has some sample code.
There might be more then just one worker waiting for a condition to become true.
If two or more worker get awake (notifyAll) they have to check the condition again.
otherwise all workers would continue even though there might only be data for one of them.
I think I got #Gray 's answer.
Let me try to rephrase that for newbies like me and request the experts to correct me if I am wrong.
Consumer synchronized block::
synchronized (queue) {
// this needs to be while
while (queue.isEmpty()) {
queue.wait();
}
queue.remove();
}
Producer synchronized block::
synchronized(queue) {
// producer produces inside the queue
queue.notify();
}
Assume the following happens in the given order:
1) consumer#2 gets inside the consumer synchronized block and is waiting since queue is empty.
2) Now, producer obtains the lock on queueand inserts inside the queue and calls notify().
Now,either consumer#1 can be chosen to run which is waiting for queue lock to enter the synchronized block for the first time
or
consumer#2 can be chosen to run.
3) say, consumer#1 is chosen to continue with the execution. When it checks the condition,it will be true and it will remove() from the queue.
4) say,consumer#2 is proceeding from where it halted its execution (the line after the wait() method). If 'while' condition is not there (instead an if condition), it will just proceed to call remove() which might result in an exception/unexpected behaviour.
Because wait and notify are used to implement [condition variables](http://en.wikipedia.org/wiki/Monitor_(synchronization)#Blocking_condition_variables) and so you need to check whether the specific predicate you're waiting on is true before continuing.
Both safety and liveness are concerns when using the wait/notify mechanism. The safety property requires that all objects maintain consistent states in a multithreaded environment. The liveness property requires that every operation or method invocation execute to completion without interruption.
To guarantee liveness, programs must test the while loop condition before invoking the wait() method. This early test checks whether another thread has already satisfied the condition predicate and sent a notification. Invoking the wait() method after the notification has been sent results in indefinite blocking.
To guarantee safety, programs must test the while loop condition after returning from the wait() method. Although wait() is intended to block indefinitely until a notification is received, it still must be encased within a loop to prevent the following vulnerabilities:
Thread in the middle: A third thread can acquire the lock on the shared object during the interval between a notification being sent and the receiving thread resuming execution. This third thread can change the state of the object, leaving it inconsistent. This is a time-of-check, time-of-use (TOCTOU) race condition.
Malicious notification: A random or malicious notification can be received when the condition predicate is false. Such a notification would cancel the wait() method.
Misdelivered notification: The order in which threads execute after receipt of a notifyAll() signal is unspecified. Consequently, an unrelated thread could start executing and discover that its condition predicate is satisfied. Consequently, it could resume execution despite being required to remain dormant.
Spurious wakeups: Certain Java Virtual Machine (JVM) implementations are vulnerable to spurious wakeups that result in waiting threads waking up even without a notification.
For these reasons, programs must check the condition predicate after the wait() method returns. A while loop is the best choice for checking the condition predicate both before and after invoking wait().
Similarly, the await() method of the Condition interface also must be invoked inside a loop. According to the Java API, Interface Condition
When waiting upon a Condition, a "spurious wakeup" is permitted to
occur, in general, as a concession to the underlying platform
semantics. This has little practical impact on most application
programs as a Condition should always be waited upon in a loop,
testing the state predicate that is being waited for. An
implementation is free to remove the possibility of spurious wakeups
but it is recommended that applications programmers always assume that
they can occur and so always wait in a loop.
New code should use the java.util.concurrent.locks concurrency utilities in place of the wait/notify mechanism. However, legacy code that complies with the other requirements of this rule is permitted to depend on the wait/notify mechanism.
Noncompliant Code Example
This noncompliant code example invokes the wait() method inside a traditional if block and fails to check the postcondition after the notification is received. If the notification were accidental or malicious, the thread could wake up prematurely.
synchronized (object) {
if (<condition does not hold>) {
object.wait();
}
// Proceed when condition holds
}
Compliant Solution
This compliant solution calls the wait() method from within a while loop to check the condition both before and after the call to wait():
synchronized (object) {
while (<condition does not hold>) {
object.wait();
}
// Proceed when condition holds
}
Invocations of the java.util.concurrent.locks.Condition.await() method also must be enclosed in a similar loop.
Before getting to the answer, lets see how wait is probably implemented.
wait(mutex) {
// automatically release mutex
// and go on wait queue
// ... wait ... wait ... wait ...
// remove from queue
// re-acquire mutex
// exit the wait operation
}
In your example mutex is the obj with the assumption that your code is running inside synchronized(obj) { } block.
A mutex is called as monitor in Java [some subtle differences though]
A concurrency example using condition variable with if
synchronized(obj) {
if (!condition) {
obj.wait();
}
// Do some stuff related to condition
condition = false;
}
Lets say we have 2 threads. Thread 1 and Thread 2.
Lets see some states along the timeline.
at t = x
Thread 1 state:
waiting on ... wait ... wait ... wait ..
Thread 2 state:
Just entered the synchronised section, since as per the thread 1's state, the mutex/monitor is released.
You can read more about wait() here java.sun.com/javase/6/docs/api/java/lang/Object.html#wait(long).
This is the only thing that is tricky to understand. When 1 thread is inside the synchronized block. Another thread can still enter the synchronized block because wait() causes the monitor/mutex to be released.
Thread 2 is about to read if (!condition) statement.
at t = x + 1
notify() is triggered by some thread on this mutex/monitor.
condition becomes true
Thread 1 state:
Waiting at re-acquire mutex, [Since thread-2 has the lock now]
Thread 2 state:
Doesn't go inside if condition and marks the condition = false.
at t = x + 2
Thread 1 state:
Exits the wait operation and about to mark condition = false.
This state is inconsistent as condition is supposed to be true but is false already, because thread 2 marked it false previously.
And thats the reason, while is required instead of if. As while would trigger the condition to be checked again for thread 1 and thread 1 will begin waiting again.
Result
In order to avoid this inconsistency the correct code seems to be like this:
synchronized(obj) {
while (!condition) {
obj.wait();
}
// Do some stuff related to condition
condition = false;
}
From your Question:
I have read that we should always called a wait() from within a loop:
Although wait( ) normally waits until notify( ) or notifyAll( ) is called, there is a possibility that in very rare cases the waiting thread could be awakened due to a spurious wakeup. In this case, a waiting thread resumes without notify( ) or notifyAll( ) having been called.
In essence, the thread resumes for no apparent reason.
Because of this remote possibility, Oracle recommends that calls to wait( ) should take place within a loop that checks the condition on which the thread is waiting.
Three things you will see people do:
Using wait without checking anything (BROKEN)
Using wait with a condition, using an if check first (BROKEN).
Using wait in a loop, where the loop test checks the condition (NOT BROKEN).
Not appreciating these details about how wait and notify work leads people to choose the wrong approach:
One is that a thread doesn't remember notifications that happened before it got around to waiting. The notify and notifyAll methods only effect threads that are already waiting, if a thread isn't waiting at the time it is out of luck.
Another is that a thread releases the lock once it starts waiting. Once it gets a notification it re-acquires the lock and continues on where it left off. Releasing the lock means that thread does not know anything about the current state once it wakes back up, any number of other threads could have made changes since then. The check made before the thread started waiting doesn't tell you anything about what the state is currently.
So the first case, with no checking, makes your code vulnerable to race conditions. It might happen to work by accident if one thread has enough of a head start over another. Or you may have threads waiting forever. If you sprinkle in timeouts then you end up with slow code that sometimes doesn't do what you want.
Adding a condition to check apart from the notification itself protects your code from these race conditions and gives your code a way to know what the state is even if the thread wasn't waiting at the right time.
The second case, with if-checks, is likely to work if you have only 2 threads. That puts a limit on the number of states things can get into and when you made faulty assumptions you don't get burned so badly. This is the situation for lots of toy example code exercises. The result is people come away thinking they understand, when they really don't.
Protip: Real world code has more than two threads.
Using the loop lets you re-check the condition once you re-acquire the lock so that you're moving forward based on current state, not on stale state.
In simple words,
'if' is a conditional statement , once condition is satisfied remaining block of code will get executed.
'while' is a loop which going check the condition unless condition is not satisfied.
If I use this method like this, will it interrupt the thread or not?
while ( !interrupted() && more work to do){ /* main thread execution loop*/ }
2nd question: what does this statement mean?
interrupt() method, does not automatically mean that the thread should
terminate. It simply grabs the attention of the thread (kind of like
poking a sleeping roommate to wake him up)
Calling interrupted() does not “interrupt” execution of code in the Thread. Your condition will, however, cause the loop to exit if the Thread running it is interrupted by another thread calling interrupt() on it, assuming no other code in the loop calls interrupted() (which clears the current Thread’s interrupted status).
The text you have quoted is explaining that a Thread’s code must act on an interrupt, by checking the Thread’s interrupted status, or by calling a method capable of throwing InterruptedException (or ClosedByInterruptException). If the Thread’s code does none of those things, calling interrupt() on that Thread will have no effect on code execution; it will merely set the Thread’s interrupted status, which is just a boolean property of the Thread. Code must properly respond to interrupts for interrupts to be effective.
Well, I have a thread in my video converter which is responsible for transcoding the video. It is a user thread with setDaemon(false).
To stop it, I call the threadName.interrupt() method however, it does not stop. It continues on !
How do I stop it?
Here is how I try to stop it:
if(getExecutingTaskID() == taskID){
int what = JOptionPane.showOptionDialog(frame,
"Do you want to interrupt an executing task?",
"Task already running",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null, null, null);
if(what == JOptionPane.YES_OPTION){
if(getExecutingTaskID() == taskID){
converter.interrupt();
}
return true;
}
}
return false;
}
A thread can only be interrupted when it calls a method that throws InterruptedException or if it calls Thread.interrupted and is coded to respond to it. If you want to be able to break your thread at any time, you'll need to build that into the code itself. Oracle provides a tutorial. Basically, your options are to use methods that throw InterruptedExcetion like sleep or wait, to periodically call Thread.interrupted, or have your own stop variable that you check periodically.
No matter how you slice it, you have to implement the interrupt. Java just has some simple ways of getting the message to the thread.
There is a Thread.stop method, but this method is considered extremely dangerous. This stops the thread and immediately releases all locks, which may leave objects in an unusable state. Using it is generally just a bad idea.
(Sorry to the major revamp of the answer.)
Quoting from the Java Tutorials (emphasis mine):
"An interrupt is an indication to a thread that it should stop what it is doing..."
"It's up to the programmer to decide exactly how a thread responds to an interrupt..."
"For the interrupt mechanism to work correctly, the interrupted thread must support its own interruption..."
Essentially, you have to watch for the "Interrupted" flag from within the thread and terminate it "from inside" when you detect the flag has been set. There are several ways to check for and handle interruption (see the link above) - e.g. you could use Thread's interrupted() method.
I don't know the inner workings of your readers and converters, but this while-loop seems like a good canditate for implementing the check:
while (reader.readPacket() == null) {
// code the next packet
...
// Check for interruption
if (Thread.interrupted()) {
// We've been interrupted: terminate
return;
}
}
There are 3 ways to terminate a thread:
The thread has finished the work it is designed to do, and exits the
run() method naturally.
The thread has received an interruption signal, while doing its
work. It decides to not continue with work and exits the run()
method. It may also decide to ignore the signal and continue to
work.
The thread has been marked as daemon thread. When the parent thread
who created this thread terminates, this thread will be forcefully
terminated by the JVM.
See this thread by Sun on why they deprecated Thread.stop(). It goes into detail about why this was a bad method and what should be done to safely stop threads in general.
http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
The way they recomend is to use a shared variable as a flag which asks the background thread to stop. This variable can then be set by a different object requesting the thread terminate.
Suppose during my running I would like to shutdown a single thread gracefully!
I don't want to use Thread.stop() nor Thread.destroy() due to their unsafe behavior.
Note: I'm familiar with using ExecutorService.shutdown() option.
But I would like to know the other way to implement.
The standard way to stop a thread is to call thread.interrupt();. To make it work, you need to make sure you thread responds to interruption, for example:
Thread t = new Thread(new Runnable() { public void run {
while(!Thread.currentThread().isInterrupted()) {
//your code here
}
}});
t.start();
t.interrupt();
This only works if the condition is checked regularly. Note that you can delegate the interruption mechanism to interruptible methods (typically I/O, blocking queues, sleep/wait provide methods that can block until they are interrupted).
Note: In this example, you can also use:
while(!interrupted()) {
//your code here
}
interrupted() does the same thing as Thread.currentThread().isInterrupted() except that the interrupted flag is reset. Since it is your thread, it does not matter.
You could have isStopped()flag in your code. And the running thread should regularly check this flag to see if it should stop. Note that stopping a thread gracefully requires the running code to be written in a way that allows stopping.
You can take a look at this question for some more detailed answers
You have to make the run() method of the thread terminate for some reason. How you achieve this depends on what the thread does.
If the thread is looping, you can stop it by raising a flag (checked by the condition of the loop).
If the thread is waiting over a Socket or any other stream, just close the stream.
If the thread is blocked on a call that can throw an InterruptedException, you can interrupt() the thread and ignore the exception.
If the thread is consuming the elements of a blocking queue, use the poison pill method, which means putting on the queue an element that just means "stop looping".
If you have a loop inside your run() method of your Thread then one option would be that your loop checks for the value of a flag on every iteration.
You can set the flag from outside the code, such as your thread would stop executing before starting the next iteration.
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?
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!
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.
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.
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 returning 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.
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.
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.
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
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.
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:
If your you are in Runnable.run() just return or break out of the loop and finish the method.
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).
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:
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.
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.