Summary
In his latest DeveloperWorks article, Brian Goetz discusses strategies for dealing with InterruptedException. The article shows how swallowing InterruptedException can lead to unpredictable application behavior, and outlines strategies for cancellable tasks as a way to manage this aspect of Java concurrency.
Advertisement
Most developers deal with InterruptedException by simply swallowing it. Brian Goetz in his recent DeveloperWorks article shows why this is wrong:
The worst thing you can do with InterruptedException is swallow it—catch it and neither rethrow it nor reassert the thread's interrupted status. The standard approach to dealing with an exception you didn't plan for—catch it and log it—also counts as swallowing the interruption because code higher up on the call stack won't be able to find out about it. (Logging InterruptedException is also just silly because by the time a human reads the log, it is too late to do anything about it.)
The article explains the notion of a blocking method:
When a method throws InterruptedException ... it is telling you that it is a blocking method and that it will make an attempt to unblock and return early—if you ask nicely... The completion of a blocking method ... is ... dependent on some external event, such as timer expiration, I/O completion, or the action of another thread (releasing a lock, setting a flag, or placing a task on a work queue). Ordinary methods complete as soon as their work can be done, but blocking methods are less predictable because they depend on external events. Blocking methods can compromise responsiveness because it can be hard to predict when they will complete.
A method that calls a blocking method becomes a blocking method as well. The main benefit of InterruptedException is the ability to deal with blocking methods by allowing cancellation of such methods from another thread and then letting the interrupted thread perform cleanup work.
For instance, in a GUI application, the user might be given a chance to interrupt a blocking method, or in a server application a monitoring component can cancel a task given some operational conditions, such as a timeout. When a caller interrupts a blocking method, the blocking method will have an opportunity to perform cleanup work by handling InterruptedException.
If no special cleanup is required, the article suggests that the blocking method should handle InterruptedException by re-interrupting the current thread:
public void run() {
try {
while (true) {
Task task = queue.take(10, TimeUnit.SECONDS);
task.execute();
}
}
catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
}
The main reason for doing is that the interruption request that resulted in InterruptedException may have multiple recipients:
The standard thread pool (ThreadPoolExecutor) worker thread implementation is responsive to interruption, so interrupting a task running in a thread pool may have the effect of both canceling the task and notifying the execution thread that the thread pool is shutting down. If the task were to swallow the interrupt request, the worker thread might not learn that an interrupt was requested, which could delay the application or service shutdown.
What do you think of the article's conclusions? What are your strategies for handling blocking methods, and how do you deal with InterruptedException in your code?