I have a question for the below statements
When a thread is a new thread, it is merely an empty Thread object. No
system resources have been allocated for it yet. When a thread is in
this state, you can only start the thread or stop it. Calling any
method besides start or stop when a thread is in this state makes no
sense and causes an IllegalThreadStateException.
Why does java allow to stop a thread which is not even started... in which scenario one will have to invoke stop() and a new thread?
First of all do no use the function which have been marked as deprecated.
As the documentation indicates for Stop,
It is permitted to stop a thread that has not yet been started. If the thread is eventually started, it immediately terminates.
Moreover, if I look at the code for Stop which is
#Deprecated
public final void stop() {
// If the thread is already dead, return.
// A zero status value corresponds to "NEW".
if ((threadStatus != 0) && !isAlive()) {
return;
}
stop1(new ThreadDeath());
}
As you can see from code it is designed such that, it returns normally when threadStatus != 0 (A zero status value corresponds to state "NEW") or if the thread is already stopped.
Other answers address the specifics, so I'll try talking about the more general idea behind it.
Essentially, if designers don't allow methods being called, they are trying to detect programming errors. In the designers view, interrupt() being called when the thread was never started seemed likely to be a bug, whereas the same for stop() seemed less so.
There are other similar examples, too. For example, Future#cancel() can be called multiple times.
Ultimately I think there is an element of subjectivity/preference, even though in some cases one makes clearly more sense than the other.
Related
Thread class has many static methods that are called by class name. Some of them are:
But yet, we are provided with method currentThread() that returns currently executing thread object. Some are:
Unfortunately, this created confusion in my head. When I think of a method I want, I have no clue whether I would found it as static or instance. So why did they make such two approaches?
I mean, couldn't they all be grouped in same 'calling'? For example why is sleep() static and not instance method called with Thread.currentThread().sleep()? Another weird example is between interrupted() and isInterrupted() defined in different manner. They do exactly the same thing, just interrupted() additionally clears interrupted flag. Has anyone logic answer to this, so I have no struggle where to find each method?
It's tricky; the answer is different for each method. Let's go through the ones you named:
Thread.sleep
Imagine I called: someOtherThread.sleep(1000L);. What would this mean? Surely that ought to mean: Sleep that other thread, not my thread. Except that's not something java offers: You can sleep your own thread, but you cannot arbitrarily tell some other thread to freeze like they're doing a mime act, mid execution of some arbitrary command. For example, if that thread is currently blocked on, say, waiting for the OS to deliver some bytes from a file read, that definitely cannot just fall asleep, and there are many, many other scenarios where a thread cannot do that.
Thus, java does not offer this functionality - you can't sleep other threads. Only your own. There are two different ways to make this at least somewhat clear in API design:
The first is to have sleep be an instance method (thus, you'd have to write e.g. Thread.currentThread().sleep(1000L);), and spec the method that it will guaranteed, always, immediately throw an IllegalStateException if you invoke it on any thread except your own. This means a compile/write-time detectable error condition would only be caught at runtime (this is bad; catching a problem earlier is obviously better than catching it later), it makes the code you'd have to write to sleep needlessly longer, and the existence of a sleep method you can invoke on thread instances sure suggests that you can sleep other threads. It'd just be crappy API design.
The second is to make sleep static.
Think of it this way: java.lang.Thread is a container for two mostly unrelated batches of methods: One is a set of methods you can use on threads (those'd be the instance methods). The other is a bunch of thread and flow related primitives, such as 'sleep', 'yield', and interrupt interaction. They just happen to be shoved into the same class.
interrupt
This is probably the trickiest. Unlike sleeping, you can in fact ask another thread's interrupt flag status.
The reason there are two methods are because of the more or less intended API design of the interrupt system.
The interrupt system is designed as follows:
If you want some thread to stop what it is doing for some unspecified reason (for example, you want it to re-check some condition, or just cease running, or anything else you can think of) then you need a mechanism to signal this. In particular, you'd want such a mechanism to ensure that any interruptable blocking operations, such as Thread.sleep(100000L) are interrupted. In other words, you can't just say: Whatever, it's up to the code itself, just, um, make an AtomicBoolean and check it a lot.
That's where the 'interrupt' system comes in. The idea is:
To interrupt any thread, raise its interrupt flag, with thatThread.interrupt();
All methods that do interruptable things should check this flag. The procedure is: If it is raised, then [A] clear it, and [B] handle the interruption, doing whatever the programmer intended to happen upon interruption (just stop running, or re-check some condition, re-read some config file, who knows - it's programming, whatever you want it to mean). If you CAN handle the notion of aborting some operation, but you CANNOT handle it, then instead clear that flag and throw InterruptedException, so that the caller can handle it.
As a result, any code that knows what 'I was interrupted!' means should BOTH check the flag (especially if that code has an event loop, which most thread-based code does have), AND catch InterruptedException from any method specced to throw it, and react in the exact same way to either catching that exception or having Thread.interrupted() return true.
Things go all sorts of wrong if you handle the fact that the interrupt flag is up, but you do NOT lower it. For example, if you abort your CPU-bound bitcoin mining or whatnot and just return back to your caller whilst leaving the flag up, then the next time caller invokes Thread.sleep, thread.sleep will notice the flag is up and IMMEDIATELY exit, not sleeping at all (exit by throwing InterruptedException, to be specific). That isn't intended. Hence why it is important that if you respond to an interrupt, you lower that flag.
So, let's go back to API design. There are two strategies:
Hypothetical design A
while (!Thread.currentThread().isInterrupted()) {
mineAnotherBitCoin();
}
Thread.currentThread().clearInterruptFlag();
Design B
while (!Thread.checkAndClearInterruptFlag()) {
mineAnotherBitCoin();
}
Note how design B is conceptually a lot shorter, does not have a 'gap' between checking the flag and clearing it, and therefore is fundamentally less error prone. Furthermore, for, well, reasons, it has been decided that raising an interrupt flag is something you can do to other threads (there is no point interrupting yourself, after all), but clearing one is a thing you can only do to your own thread.
B is what java actually has, except the method is somewhat strangely named interrupted(), and not checkAndClearInterruptFlag(). If you want an explanation of why some methods in java are somewhat suspectly named, it's because java does not like breaking backwards compatibility.
Fundamentally then, while they sound real similar, isInterrupted() and interrupted() do two very different things.
isInterrupted() is to check if some thread has already been interrupted and its response to this interruption is still pending (nothing has yet handled it).
interrupted() is something you put in the condition in your while loops that define the core body of your thread implementation (your 'event loop').
*) It doesn't help that the vast majority of examples of how to make threads in java are erroneous in that they don't properly do this. They tend to be while (true) or while (!running) {} or similar, either ignoring interruptions entirely or with a handrolled interrupt-esque 'running' concept.
So how do I know where to look?
Simple enough: If it's a thing that conceptually doesn't belong to any particular thread (such as 'how many threads are active right now'), or it is a utility concept (such as 'sleep'), or it is a thing that from a VM design principle can only be done to your own thread and not to anything else, then it is a static method in Thread.
If it's a thing that does belong to a particular thread AND the VM would let you do it to other threads (such as interrupting it, asking for its name, id, or priority, getting a stack dump, freezing this thread until the other thread completes, or setting its priority), then it's an instance method.
In many ways you can reverse this logic: If you want to do some thread related business, check the Thread class for something that seems to describe what you want. Then check if the method is static or not. If it is static, you don't get to do it to any other thread (such as clearing the interrupt flag, or sleep). If it's instance, you CAN do that to other threads (such as changing its priority level).
Because you can't make another thread sleep that is not the thread you are on. Even when you call Thread.currentThread().sleep(), you are calling the static method 'sleep'. If you were to call the sleep method on a different Thread object, it would still make the current thread sleep.
If you want to make a different thread sleep, you should set a flag that the other thread reads, which causes it to sleep.
I've finally managed to implement Thread.interrupt() into my program instead of Thread.stop(). I am however not sure that I've done this well.
I have a class which extends Thread and declares several methods. EVERY method has been made to throw InterruptedException (Each method performs I/O intensive operations, some of which take several minutes to complete, I have therefore not used a thread-safe flag as the flag would not get checked until after the operation completed). I have also added the following code at several places within these methods to throw the exceptions:
if (this.isInterrupted()) throw new InterruptedException();
Within the run() method I execute all methods within a try/catch for InterruptedException. If caught, I execute Process.destroy() and BufferedReader.close() for my class variables.
This all works, and seems to work very well, however I have a couple of questions:
Is it correct to have more than 10 methods, all of which throw InterruptedException? Is there a better way to do this?
Is it correct to bloat the methods with checks for isInterrupted()?
At the end of the catch InterruptedException block, must I execute a 'return', or 'null' certain values to make the Thread available for GC? If I re-create the Thread it takes longer than usual to initialize.
Finally, are there any issues/enhancements related to what I've done?
Thanks in advance for your help!
Thread interruption in Java doesn't mean stopping the execution of that thread. It is not stop, it is interrupt. A thread can be interrupted when something fundamental and crucial changes, telling the thread that its execution context, its task or its enviroment changed in some significant way. A thread reaction to this message is implementation specific. It can be stop, it can be restart or any other action. A thread that doesn't handle interruptions cannot be interrupted, but its behaviour can still be altered, for example, by using a shared variable.
For example, imagine you have a number of threads, all searching through a part of a problem space for a solution. When one thread finds a solution, it can interrupt other threads, because their search for a solution is no longer relevant. A solution has already been found.
Or imagine one continuously working main thread and one network communication thread. Each time the network thread receives a messsage, it interrupts the working thread with the message. Based on what the message and the context is, the worker thread may decide what to do next. For example, if the message was "STOP", then it could stop all execution immediately. If the message was "RESET", it could start again from scratch or maybe not from scratch and reuse some previous work, based on the execution context.
Is it correct to have more than 10 methods, all of which throw
InterruptedException? Is there a better way to do this?
No, this is perfectly fine, as long as you know what you are doing. If you implement interruptions to just stop the threads, there is no need to throw InterruptedExceptions. A Thread's run() method is it's first, and the exception will not go any further the stack.
Is it correct to bloat the methods with checks for isInterrupted()?
Depending on the context. The checks would be usually added before some crucial code. Usually it is added as a first item in the loop block.
At the end of the catch InterruptedException block, must I execute a
'return', or 'null' certain values to make the Thread available for
GC? If I re-create the Thread it takes longer than usual to
initialize.
No. Once the Thread exists from the run() method, it's left at GC's mercy. Shared variables will not be GC'ed, as long as they are still referenced by other objects.
I am actually looking for an easier way to kill the thread not matter where the thread is running at. But most of the solutions in internet point me to use boolean flag to control the execution of the thread, if I want to stop the thread then set the boolean variable to false.
But what if the task that in the runnable is a LONG linear task, which mean the task is not repeating? In that case, it is not so easy to create a 'while' loop to cover the whole block of task.
It is really so temptative to use Thread.stop but the warning "Deprecated" seem like quite dangerous to use. I have read through this article
Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?
but I can't understand
If any of the objects previously protected by these monitors were in
an inconsistent state, other threads may now view these objects in an
inconsistent state. Such objects are said to be damaged.
What does the "inconsistent state" mean? I appreciate if anyone can explain about this.
I want to extend my question to a more lower level of view, let say i = i + 1; in JVM (perhaps assembly language alike), maybe this Java statement will be split into few smaller instructions, for example like move i ; add i ; get i into memory 0x0101 (This is an example! I totally don't know assembly language!)
Now, if we call thread.stop, where actually will it stop at? Will the thread stop after a COMPLETED Java statement, or could be in the middle of the "assemble language"? If the answer is the second, could it be reason that we said
Such objects are said to be damaged.
?
Ok, my question is kind of confused, hope someone can understand and explain. Thanks in advance.
"Damaged object" is a high-level concept, it doesn't happen at the JVM level. A programmer designs his class with thread safety in mind by guarding critical sections with locks. It is an invariant of his class that each critical section either runs in full, or doesn't run at all. When you stop a thread, a critical section may have been interrupted in the middle, so disrupting the invariant. At that moment the object is damaged.
Stopping a thread conceals many more dangers, like no cleanup performed, no acquired resources released, etc. If a thread doesn't give up what it is doing, there is no way to make it stop without compromising the entire application.
In practice, whenever one faces the need to run alien code that may need to be forcefully aborted, this must be done in a separate process because killing a process at least performs OS-level cleanup and does a much better job of containing the damage.
The "inconsistent state" means state of data as your application cares about, state that your application logic have carefully produced by making your application thread-safe with locks/monitors etc.
Imagine you have this simple method:
public synchronized void doSomething()
{
count++;
average = count/total;
}
This method, along with other methods are synchronized, as multiple threads are using this object.
Perhaps there's a
public synchronized AverageAndCount getMeasurement()
{
return new AverageAndCount(average, count);
}
This assures that a thread can't read an incomplete measurement, i.e. if the current measurement is in the process of being calculated inside e.g. doSomething(), getMeasurement() will block/wait until that's finished.
Now, imagine the doSomething is run in a thread, and you call .stop() on that thread.
So the thread might be stopped right after it performs count++;, the monitor that's held is unlocked and the method terminates and average = count/total; is not executed,
That means the data is now inconsistent. Anyone calling getMeasurement() afterwards will now get inconsistent data.
Note also that at this point it is not very relevant whether this happens at a java statement level, or at a lower level, the data can be in an inconsistent state that you can't reason about in any case.
I'm no expert but this is what I think.
If you use Thread.stop() you cause the ThreadDeath exception that will cause all monitors to be released.
Since you provoke an exception you are applying an unnatural behaviour to the state of things.
Other threads relying on those monitors could enter in an inconsistent situation because they were not expecting it. And I don't think you can even anticipate the monitors releasing order.
I believe the concern is that the thread may be in the middle of a synchronize block performing multi-step updates to an object's members. If the thread is stopped abruptly, then some updates will have occurred but not others and now the object's state may render it unusable.
I have my doubts that the ThreadDeath handling will release a Lock backed by the AbstractQueuedSynchronizer which could leave the application on the path to a sort of deadlock.
At any logical point in your long sequence of code you can simply add:
if (Thread.interrupted()) {
throw new InterruptedException();
}
...this will exit execution at this point if it is determined that Thread.interupt() was called on the Thread executing the long running task.
It's not clear way to stop the thread.actually deprecated the stop() method whenever run() method is completed or any exception is occurred then thread is stop.by using the boolean flag variable .Bydefault "false"
As many others I have a problem killing my thread without using stop().
I have tried to use volatile on a variable with a while loop in my threads run() routine.
The problem is as far as I can see, that the while loop only checks the variable before every turn. The complex routine Im running takes a long time, and because of that the thread is not terminated immediately.
The thread I want to terminate is a routine that connects to another server and it uses a looooong time. And I want to have an abort button for this. (Terminating the thread). I'll try to explane with some code.
class MyConnectClass{
Thread conThread;
volitile boolean threadTerminator = false;
..some code with connect and abort button..
public void actionPerformed(ActionEvent e) {
String btnName = e.getActionCommand();
if(btnName.equalsIgnoreCase("terminate")){
threadTerminator = true;
conThread.interrupt();
System.out.println("#INFO# USER ABORTED CURRENT OPERATION!");
}else if(btnName.equalsIgnoreCase("connectToServer")){
conThread = new Thread() {
public void run() {
while(threadTerminator == false){
doComplexConnect(); //Uses a loooong time
}
}
}
conThread.start();
}
}
}
How can I kill my "connection" thread instantly?
Thanks.
Java abandoned the stop() approach in Threads a while back because killing a Thread ungracefully caused huge problems in the JVM. From the Javadoc for stop():
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.
In most cases, it is up to you to check the threadTerminator var whenever it is safe for you to terminate, and handle the thread exit gracefully. See http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
If you are doing long I/O, you may be in trouble. Some I/O operations throw an InterruptedException, in which case, you can interrupt the thread, and, if you were in that I/O, that exception will be thrown more or less instantly, and you can abort and cleanup the thread. For this reason, interrupting a thread is preferable to using a special custom threadTerminator variable - it's much more standard. In you main code outside of the I/O, check for interrupted() or isInterrupted() periodically (instead of threadTerminator == false).
If you are doing I/O that doesn't throw InterruptedException, sometimes you can close the Socket or similar, and catch the IOException. And sometimes you are stuck.
Why don't you interrupt the thread and just move on, letting it hang until it finishes? The user could initiate a different action (thread) while the old thread finishes gracefully (which, from what I see you are pretty much doing already btw)
The downside of this that you have trouble when the user starts clicking "connectToServer" a lot (many threads), or when the threads fail to terminate (hanged threads). But maybe it's sufficient for your purpose?
Edit:
It would be simple to implement a mechanism that prevents spawning a new conthread unless "it's good to go" (e.g., use a semaphore).
The tricky part will be deciding whether it's good to open a new connection. You could ask the original thread (I.e. have a isalive() method), or the party you are trying to connect to. Or you could go for a timeout solution. For example, you could let conthread update a timestamp and decide it's dead if the timestamp isn't updated for 1 min etc. The most generally applicable solution would probably be the timeout solution.
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.