Java 5: java.util.concurrent.FutureTask - Semantics of cancel() and done() - java

I am currently hunting a nasty bug in a multi-threaded environment using FutureTasks and Executors. The basic idea is this to have a fixed number of threads execute individual FutureTasks that compute a result that is to be displayed in a a table (never mind the GUI aspect here).
I have been looking at this for so long, I am beginning to doubt my sanity.
Consider this piece of code:
public class MyTask extends FutureTask<Result> {
private String cellId;
...
protected void done() {
if (isCancelled()) return;
try {
Result r = get(); // should not wait, because we are done
... // some processing with r
sendMessage(cellId, r);
} catch (ExecutionException e) { // thrown from get
...
} catch (InterruptedException e) { // thrown from get
...
}
}
...
}
When done() is called by an Executor handling an instance of MyTask, I check if I got there, because the task was cancelled. If so, I skip all remaining activities, especially I do not call sendMessage().
The documentation for FutureTask.done() says:
Protected method invoked when this task transitions to state isDone (whether normally or via cancellation). The default implementation does nothing. Subclasses may override this method to invoke completion callbacks or perform bookkeeping. Note that you can query status inside the implementation of this method to determine whether this task has been cancelled.
(API Reference)
But what I do not get from the documentation of FutureTask are the semantics while done() is being executed. What if I pass the isCancelled() check at the beginning, but right after that some other thread calls my cancel() method? Will that cause my task to change its mind and reply isCancelled() == true from then on?
If so, how would I later know if the the message was sent? Looking at isDone() would just tell me that execution of the task was finished, but as isCancelled() were true then as well, I could not know if it got to send the message out in time.
Maybe this is obvious, but I do not really see it right now.

FutureTask#done() is called no more than once for any given instance, and it's only called for one reason -- run() completed either with or without error, or cancel() ran before either of the preceding events occurred. The record of completion by any of these outcomes is latching. The reason a FutureTask completed can't change, regardless of competing events seemingly happening "at the same time."
Hence, within FutureTask#done() only one of isCancelled() or isDone() will return true then and forever more. It's difficult to distinguish between isDone() reporting true by way of error or successful completion. You can't override set() or setException(Throwable) decisively, as both delegate to the inner AQS to decide whether the attempt to record a successful yielding of a value or encountering an exception should stick. Overriding either method only lets you know that it was called, but you can't observe the decision made by the base implementation. If either event occurs "too late"—say, after cancellation—the attempt to record the value or the exception will be ignored.
Studying the implementation, the only way I see to discern a non-canceled successful outcome from an error is to bite the bullet and call get().

From the API (emphasis mine):
public boolean cancel(boolean mayInterruptIfRunning)
Description copied from interface: Future
Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason.
So FutureTask is working off the assumption that you cannot cancel a task when it has transitioned to the isDone stage.

Why not send the message "outside" of the task, based on the outcome of the Future<V> object returned by an ExecutorService? I've used this pattern and it seems to work well: Submit a bunch of Callable<V> tasks through an ExecutorService. Then, for each primary task, submit a secondary task that waits on the Future<V> of the primary task and does some follow-up action (like send a message) only if the Future<V> indicates that the primary task completed successfully. There is no guesswork with this approach. When the call to Future<V>.get() returns, you're guaranteed that the task has reached a terminal state, as long as you don't call the version of get that takes a timeout argument.
If you take this approach, you should use two separate ExecutorService instances: one for the primary tasks and one for the secondary ones. This is to prevent deadlocks. You don't want secondary tasks to start up and potentially block primary tasks from starting when the thread pool size is limited.
There's no need to extend FutureTask<V> at all. Just implement your tasks as Callable<V> objects. But if for some reason you want to detect if the task was canceled from within the Callable<V> code, just check the interrupt status of the thread with Thread.interrupted().

I suggest to write a small test case which allows you to call cancel() while your Future instance hangs in done() and see what happens.

Related

Thread with capability of stopping it in any duration of time

is there any kind of Runnable, Callable or Thread with capability of stopping it in any duration of time?
I wrote something like this
public class ThreadRunner {
private ExecutorService threadPoolExecutor;
ThreadRunner() {
threadPoolExecutor = Executors.newSingleThreadExecutor();
}
public void startThread(String endPoint, ProgressBar progressBar) {
Runnable task = () -> {
// some code which saves images from URL (1230 images) and updates progress bar
};
threadPoolExecutor.execute(task);
}
public void stopThread() {
threadPoolExecutor.shutdownNow();
}
}
Thread runs correctly, images are being saved, progress bar being updated, but when I want to stop thread (or maybe even pause process of saving if possible) by calling ThreadRunner class's method - nothing happens.
Am I doing something wrong - or most likely - what am I doing wrong?
is there any kind of Runnable, Callable or Thread with capability of stopping it in any duration of time?
You can implement such a thing yourself, but there is no generic support available for it, unless you count the long-deprecated Thread.stop() methods. Under no circumstances should you use those methods, but do read their API docs for a discussion of why they are deprecated and what you can do instead. You can find a longer-form version of the discussion in Java's technical notes.
The bottom line is that the computation you want to be able to stop needs to periodically check some shared variable or built-in condition to determine whether to do so. You arrange for that variable to be set when you want the thread to stop, and if you need to block until it does stop then you join() it. Under some circumstances, it can be helpful to interrupt() the thread to get it to check the variable (or being interrupted can itself serve as the termination condition). The user-facing end of this can be wrapped up in a method.
In any case, an ExecutorService cannot give you a handle on this. Requesting such a service to shut down will prevent it from dispatching any more tasks, but there is no safe, general-purpose mechanism by which it could force a premature shutdown of tasks that are already running.
Once started, a thread will run until Runnable.run() exits. Due to several issues you should never use Thread.stop() or Thread.interrupt().
Instead, you will have to implement your own logic for exit/pause. A few suggestions:
For stopping the thread, you can make a boolean variable shouldExit. In your thread, check this variable every now and then, and just do "return" or break the for/while loop when it becomes true. Setting this variable from another thread should now make the downloader exit. If necessary, you should surround access to this variable with synchronized block as to prevent any race conditions.
For pausing the thread, you can use a similar approach. When you set a certain variable to true (e.g. isPaused), make the thread react by going into an Object.sleep(). This way, it won't consume any CPU during sleep. You can then use Object.notify() from another thread to "kick" the sleeping thread out ouf sleep. You will need a synchronized block here, too.

Spring Cancel #Async Task

I want to be able to cancel a method marked with the #Async annotation by it's future.
I have a Spring method marked with the #Async annotation. This method does some computation, and eventually returns a result. All examples I have seen recommend using the AsyncResult class to return this Future.
#Async
public Future<String> run() {
// ... Computation. Minutes pass ...
return new AsyncResult<String>("Result");
}
I call the following method, from another Component, in the following manner. For example purposes, I wish to immediately cancel this thread:
Future<String> future = component.run();
future.cancel(true);
In this case, the thread will never be cancelled. This is because, looking at the Spring implementation for AsyncResult here: https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncResult.java#L71 , this method doesn't actually do a single thing. It simply returns false, that the thread could not be cancelled. This is my problem. How can I cancel the Thread being created by the #Async method? I have no access to the internal thread being created by Spring - so I have no means myself with which to cancel it, do I?
Actually, Spring #Async uses a background thread pool of it's own. And as long as cancel() method of Future or shutdownNow() of executor service is concerned, Calling executor.shutdownNow() or future.cancel(true) don’t stop the ongoing thread immediately. What these methods do is simply call .interrupt() on the respective thread(s). And interrupts has no guaranteed immediate effect. It issues a flag so whenever in sleeping or waiting state, the thread will be stopped.
To be noted, If your tasks ignore the interruption, executor.shutdownNow() and future.cancel(true) will behave exactly the same way as executor.shutdown() and future.cancel(false).
If you need a way to stop the slow or blocking operation. If you have a long/endless loop, you can just add a condition whether Thread.currentThread().isInterrupted() and don’t continue if it is true(end the operation).

Implement a cancelable thread manager for a unique object

I need to manage many background threads that do something with some objects as key but only one thread can work with same object at the same time, For example while thread A is working on object A, if thread B called for working with object A, thread A should be canceled before thread B can run.
Here is my code, but when I run, The first thread doesn't stop and continues with second one:
private static ExecutorService mExecutor = Executors.newCachedThreadPool();
private static ConcurrentMap<Object, Future> mRunningTasks = new ConcurrentHashMap<>();
public static void run(final Runnable runnable, final Object key) {
Future<?> future = mRunningTasks.get(key);
if (future != null) {
future.cancel(true);
}
future = new FutureTask<>(new Runnable() {
#Override
public void run() {
//How to handle InterruptedException here ?
//while there's no potential to throw an InterruptedException
runnable.run();
mRunningTasks.remove(key);
}
}, null);
mRunningTasks.put(key, future);
mExecutor.execute((FutureTask) future);
}
What am I missing here ?
Thanks in advance.
PS:
I need a behavior like Picasso API when cancels requests using an ImageView as a key object.
The docs for Future.cancel() say that it attempts to cancel the task, but may be unsuccessful. You need to check the boolean return value to see if it actually cancelled.
There are multiple other raceconditions in your code.
ConcurrentHashMap is threadsafe, but the way you are using it is not.
You might:
* cancel a future multiple times
* add a future without canceling the previous one
* removing the wrong futures from the map
You should be more specific about you actually want to solve. There might be better solutions to that problem.
You want to kill the Thread (Thread.stop()), which is a very bad practice and deprecated for many reasons... Not only for don't have responsibility over the Thread, since it is managed by the ThreadPool, but killing it ruins the concept of atomicity of your algorithm, leaving your software in a possibly undetermined state.
You can cancel a FutureTask if it hasn't started. If you can't cancel it, it means it is already running. This occurs incredibly fast on modern multi-cores processors.
The ThreadPool is usually meant for short lived running Threads. But in your case, the right way to end the task properly is to set a volatile boolean variable in your Task Class and check it regularly to leave the method.
InterruptedException is only thrown when your Thread is waiting or sleeping, which is not present in your current demonstration code. If your Thread actually is waiting or sleeping, then send a .notify() to the monitor Object to interrupt it, and catch the Exception in a try {} catch()
There are two primary problems here 1) the run method needs to be declared synchronised (avoids race conditions when checking the state of things) and 2) future.cancel is not capable of halting work that has already started. So add your own guards/cancelling mechanism to the runnables.
That said, the cleanest solution is to avoid the need to cancel in the first place, however there is not enough domain detail in this question to verify if that would be feasible. A common pattern for this kind of problem is to return a promise from run and cache the promises. A promise is a thread safe container object for the result of an asynchronous operation. If the same work is scheduled twice then the same promise may be returned. If a promise has a value it would be possible to see how old the value was to determine the scheduling behaviour, such as return the old value, return the old value and schedule an update of the value behind the scenes or throw the old value away as too old and fetch a clean value.

FutureTask cancel()

Basically I have the following snippet,
(let [task (FutureTask. fn)
thr (Thread. task)]
(.start thr)
;;wait for signal...
(.cancel task true)
(.stop thr))
Problem is once in a while cancel does not work, AFAICT cancel causes and exception to be thrown but some piece of code down the line catches it? Is there a sure way to cancel a future task?
fn is a function that basically does a series of long running calculations so I can't loop checking for a boolean flag.
There is no way to stop a running task automatically in Java - in the general case it is not safe to simply "kill" an executing thread, as doing so could leave things in an inconsistent state. As a result, this ability was intentionally left out Java.
When you cancel a task, a flag is set in the executing thread, but no exception is thrown. In order to allow a task to be cancelled, you will have to write code to periodically check if the thread has been interrupted:
while (notDone) {
if (Thread.isInterrupted()){
return; // we were cancelled (or interrupted in some other way)
}
doSomeHardWork()
}
According to my (limited) knowledge, there is no general method to do that. It's because you could have one uninterruptible, remote task, you could have one task which is pure function and thus safe to kill, you could have many subtasks (as nerdytenor mentioned -- check for isInterrupted state between each), you could have mix of everything, you could have task that when killed would put other tasks in global lock state... So as far as I know you have to do it yourself.
What kind of calculations do you perform? Can you do anything inside? Maybe create some global, thread-safe table toInterrupt and check in each subtask if the whole task is about to be cancelled? I know this is very non-idiomatic but can't think of anything better for now.
Or if those are really pure-functional calculations and you are really certain about that -- kill process/thread and hope you were right.
This question probably is related Executing a function with a timeout
The macro works for my code, the thunk-timeout code is here
(defmacro with-timeout [time & body]
`(thunk-timeout (fn [] ~#body) ~time))

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

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.

Categories