Concurrency - interrupting a Future without cancelling it
Asked Answered
O

3

13

Is there any way to interrupt a Future without cancelling it?

java doc API:

boolean cancel (boolean mayInterruptIfRunning)

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.

To capture the interrupt, we have to properly catch the Interrupted Exception or check the isInterrupted() method within the Runnable / Callable method.

But there is no way to interrupt a running Future using the Future interface

Since all the threads are in the Executor Service pool, no one can do thread.interrupt(). Is that why it has been assumed that any interrupt will come only when a Future is cancelled or a Thread Pool is terminating?

I am trying to understand why there is not a interrupt method in the Future interface. Any help will be greatly appreciated

Onomastic answered 17/1, 2012 at 21:6 Comment(14)
I wonder what the point of this would be .... it's an interesting, if not odd, question.Coomb
Because of few issues. 1.) interrupting is a risk, you never know when or when the task could be interrupted, 2.) Future is not tied to any thread. Interrupting Future's thread could make break other Futures, 3.) Using the cancelling mechanism you are avoiding one of the most common pitfalls related to races and deadlocking, 4.) you get a high guarantee that your code won't be stopped in a random state.Selfdelusion
"A Future represents the result of an asynchronous computation" - wouldn't it be dangerous to interrupt an asynchronous entity seeing as the calling thread can continue to work and is waiting to hear back from the asynchronous entity?Overburden
@Rekin: Sounds like a good answer to me.Manchester
@Rekin: I concur with skaffman - why not put your comment as an answer?Overburden
Why would you want to interrupt a task if not to cancel it?Coremaker
@Selfdelusion - don't entirely agree with your answer. the Future.cancel() method does use Thread.interrupt() under the hood, so i don't understand your attempt to distinguish the 2. are you confusing Thread.interrupt() with Thread.stop()?Coremaker
Looks like the framework expects Futures to provide the result after asynchronous computation - which is fine. But the bad side is that there is no clever way to interrupt the Thread. The reason I am saying this is that we ARE interrupting the thread when we are cancelling the Future. In this case, the interrupt goes to the thread only if the thread is running. But I guess is that the Concurrency is a very delicate framework which needs to be handled very carefully - so I think the query has been answered :) Thanks for the help! I can mark this as answeredOnomastic
Currently, interrupting a Future = Stopping it. I would say that if there was an option to interrupt a Future, then based on the interrupt, the Future can do some other activity and then, if required, can go back to the original activity which it was performing But I see your point also - in a loop, the Future can check some other flag and do the other work based on that flag. I also agree that interrupting might mean that the Thread can be stopped in a random state. But isnt that on the developers to decide?Onomastic
@jtahlborn: Yes, i did exactly confuse those two. So, the right comment would be: build your own stopping mechanism on top of Future.cancel()/Thread.interrupt() instead of using dangerous Thread.stop() method, which can cause very unexpected side effects. Thanks! :)Selfdelusion
@AKSG: Yes, but the developers of the concurrency framework already decided, so it's kind of built in. But imagine, if every Future started and watched a new thread. Then, you could respond to the normal interrupt flag by stopping the second thread. So, in this twisted way, you could get the control back in a Future setting. I'm not arguing here if it's good or bad, only showing it's possible.Selfdelusion
One reason to interrupt the future is to tell it that some event has occurred based on which the future needs to do something. But at the time of the interrupt, if the future is not running, or if the future has already completed - then thats a problem. So it looks like if a future really needs to be notified of an event, it has to wait on a Lock Condition (someone can signal it). Interrupt for a Future means it is cancelled. Also, the fact that interrupt ALWAYS means cancel, makes it easire to handle interrupt within a Runnable code. This is getting much clear now :)Onomastic
@AKSG: The best source of information on the topic is probably the book: "Java Concurrency in Practice" by Joshua Bloch. For me, it's the best Java book I read so far.Selfdelusion
#3522927Blanka
R
9

The reason is because of the difference in the abstraction that is a Future and the concrete execution in a thread. We cannot say if a future is tied to a single thread or multiple thread. A future may start new threads, start new futures, etc.

Consider these abstractions as interactions between the client code and the executor of the futures. Conceptually it makes sense to say "cancel this task I have asked you to do" because it was your task to cancel. I may be busy working on it, or I may not have started it yet, or it may be finished but that's all fine, I will cancel it if you want me to. So that's why we have a cancel method.

On the other hand, it does not make as much sense to say "interrupt your task". Because of the decoupling between the result of the action (the Future) and the execution model (say an Executor), the client does not have knowledge of what actions are being taken to fulfil the task. How then can the client be expected to know when an interrupt is appropriate, required, or even supported.

Rehearing answered 22/1, 2012 at 0:18 Comment(1)
docs.oracle.com/javase/tutorial/essential/concurrency/… - An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate. But in case of the Future, interrupt means termination. I agree that whatever can be done by interrupt, the Future will have to do it by itself - like waiting for a condition. But I dont agree that interrupting a future doesnt make sense - the complexities may not be worth thoughOnomastic
G
0

At any rate you can use a timeout, so you interrupt your waiting.

get(long timeout, TimeUnit unit) 
Gosling answered 1/2, 2012 at 20:6 Comment(1)
You interrupt waiting in caller thread indeed, but no thread executing logic to obtain result from Future. There is interesting Coding challenge: partial results semantics releated to interrupting thread in order to get partial result.Nobie
B
0

There are useful usecases for doing this.

Since the problem with the Future API is that it doesn't provide the capability to detect that the execution has stopped. isCancelled() and isDone() will both happily return true even though execution of the Callable continues.

So it's really not about the level of abstraction of the Future API at this stage. But it's inability to identify task termination. Or to put differently, it's inability to differentiate between a cancel request and a completed cancel action.

One work-around is to use a CountdownLatch as done in the question Waiting for a cancelled future to actually finish . This will signal to the waiting caller that the task is actually done, and not just signaled to stop.

Blanka answered 30/1, 2016 at 0:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.