What is the proper way to handle Thread.interrupted() in a Callable? I'm guessing that the callable should throw an InterruptedException; for example:
public class MyCallable implements Callable<Object> {
public Object call() {
Object result = null;
// Simulate long-running operation that calculates result
while (true) {
...
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
result = ... // something produced by the long-running operation
return result;
}
}
Is this correct, or is there a more appropriate way to handle it? Thanks.
interrupt() method: If any thread is in sleeping or waiting for a state then using the interrupt() method, we can interrupt the execution of that thread by showing InterruptedException. A thread that is in the sleeping or waiting state can be interrupted with the help of the interrupt() method of Thread class.
interrupt() occurs while that thread is executing. The . interrupt() method sets the "interrupted" flag for that thread and interrupts any IO or sleep operations. It does nothing else, so it's up to your program to respond appropriately- and check its interrupt flag, via Thread.
currentThread(). isInterrupted() should always be used instead. The following methods will clear the interrupted flag by immediately throwing InterruptedException either if they were called and then the thread was interrupted or if the thread was already interrupted and then they were called (see junit code below).
If an InterruptedException is caught it means that the Thread. interrupt() method is called by some code, somewhere, on the currently running thread of the program. As a matter of fact, the only thing that can interrupt a thread is a call to Thread.
Edit:
After some back and forth, it seems like you want to be able to interrupt your IO routines. This seems like a good job for some of the NIO InterrutibleChannel
classes. For example, reading from the following BufferedReader
is interruptible and will throw InterruptedIOException
. See here for more examples of the NIO code.
BufferedReader in = new BufferedReader(new InputStreamReader(
Channels.newInputStream((new FileInputStream(
new File(...))).getChannel())));
Then, you can call future.cancel()
which will interrupt your thread and cause the IO to throw a InterruptedIOException
. If that happens, you could not catch the IOException
and let it trickle out of the call()
method.
If you want to pass back to the Future
that the call()
method was interrupted then I think throwing InterruptedException
is fine. Another option would be to just return null;
or some other marker object from your call()
method instead. That's typically what I do if a thread was interrupted.
One thing to remember is that if call()
throws InterruptedException
, when you do a future.get()
it will throw a ExecutionException
and the cause of that exception is going to be an InterruptedException
. Don't be confused that future.get()
can also throw a InterruptedException
itself if the get(long timeout, TimeUnit unit)
times out.
try {
result = future.get();
} catch (ExecutionException e) {
if (e.getCause() instanceof InterruptedException) {
// call() method was interrupted
}
} catch (InterruptedException e) {
// get was interrupted
}
If, however, future.cancel(true)
was called then the future.get()
will throw a CancellationException
instead.
It depends actually on how you want the thread waiting on get()
. If you do not want the waiting thread to have an exception thrown then you do not want to throw new InterruptedException
Imagine
try{
future.get();
}catch(ExecutionException ex){
}catch(InterruptedException em){
}
If any exception occurs what would you expect it to be? In your case it is an ExecutionException
. If you do not want an ExecutionException
then you should not rethrow the InterruptedException.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With