...
The task does not notify upper layers when it terminates unexpectedly as a result of the runtime exception. Moreover, it does not use any recovery mechanism.
Compliant Solution (
...
This compliant solution uses a Future
object to catch any exception thrown by the task. It uses the ExecutorService.submit()
method to submit the task so that a Future
object can be obtained.
Code Block | ||
---|---|---|
| ||
final class PoolService {
private final ExecutorService pool = Executors.newFixedThreadPool(10);
public void doSomething() {
Future<?> future = pool.submit(new Task());
// ...
try {
future.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Reset interrupted status
} catch (ExecutionException e) {
Throwable exception = e.getCause();
// Forward to exception reporter
}
}
}
|
Any exception that precludes doSomething()
from obtaining the Future
value can be handled as required.
Compliant Solution (ThreadPoolExecutor
hooks)
Wiki Markup |
---|
Task specific recovery or clean-up actions can also be performed by overriding the class {{java.util.concurrent.ThreadPoolExecutor}}'s {{afterExecute()}} hook. This hook is called when a task completes successfully by executing all statements in its {{run()}} method, or halts because of an exception (A {{java.lang.Error}} might not be captured on specific implementations, see [Bug ID 6450211|http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6450211] \[[SDN 08|AA. Java References#SDN 08]\]). When using this approach, substitute the executor service with a custom {{ThreadPoolExecutor}} that overrides the {{afterExecute()}} hook as shown below: |
...
Wiki Markup |
---|
Note that the uncaught exception handler is not called if the method {{ExecutorService.submit()}} is invoked. This is because the thrown exception is considered to be part of the return status and is consequently, re-thrown by {{Future.get()}}, wrapped in an {{ExecutionException}} \[[Goetz 06|AA. Java References#Goetz 06]\]. |
Compliant Solution (Future<V>
and submit()
)
This compliant solution uses a Future
object to catch any exception thrown by the task. It uses the ExecutorService.submit()
method to submit the task so that a Future
object can be obtained.
Code Block | ||
---|---|---|
| ||
final class PoolService { private final ExecutorService pool = Executors.newFixedThreadPool(10); public void doSomething() { Future<?> future = pool.submit(new Task()); // ... try { future.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // Reset interrupted status } catch (ExecutionException e) { Throwable exception = e.getCause(); // Forward to exception reporter } } } |
Any exception that precludes doSomething()
from obtaining the Future
value can be handled as required.
Exceptions
EX1: This guideline may be violated if the code for all runnable and callable tasks has been audited to ensure that no exceptional conditions are possible.
...