...
Compliant Solution (ThreadPoolExecutor Hooks)
Task-specific recovery or clean-up actions can be performed by overriding the {{Wiki Markup afterExecute()}} hook of the {{java.util.concurrent.ThreadPoolExecutor}} class. This hook is called either when a task concludes successfully by executing all statements in its {{run()}} method or when the task halts because of an exception. Some implementations may fail to catch {{java.lang.Error}}. (See [Bug ID 6450211|http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6450211] for more information \ [[SDN 2008|AA. References#SDN 08]\].) When using this approach, substitute the executor service with a custom {{ThreadPoolExecutor}} that overrides the {{afterExecute()}} hook:
| Code Block | ||
|---|---|---|
| ||
final class PoolService {
// The values have been hard-coded for brevity
ExecutorService pool = new CustomThreadPoolExecutor(
10, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
// ...
}
class CustomThreadPoolExecutor extends ThreadPoolExecutor {
// ... Constructor ...
public CustomThreadPoolExecutor(
int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
public void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t != null) {
// Exception occurred, forward to handler
}
// ... Perform task-specific clean-up actions
}
@Override
public void terminated() {
super.terminated();
// ... Perform final clean-up actions
}
}
|
...
| Code Block | ||
|---|---|---|
| ||
final class PoolService {
private static final ThreadFactory factory =
new ExceptionThreadFactory(new MyExceptionHandler());
private static final ExecutorService pool =
Executors.newFixedThreadPool(10, factory);
public void doSomething() {
pool.execute(new Task()); // Task is a runnable class
}
public static class ExceptionThreadFactory implements ThreadFactory {
private static final ThreadFactory defaultFactory =
Executors.defaultThreadFactory();
private final Thread.UncaughtExceptionHandler handler;
public ExceptionThreadFactory(
Thread.UncaughtExceptionHandler handler)
{
this.handler = handler;
}
@Override public Thread newThread(Runnable run) {
Thread thread = defaultFactory.newThread(run);
thread.setUncaughtExceptionHandler(handler);
return thread;
}
}
public static class MyExceptionHandler extends ExceptionReporter
implements Thread.UncaughtExceptionHandler {
// ...
@Override public void uncaughtException(Thread thread, Throwable t) {
// Recovery or logging code
}
}
}
|
...
The {{ExecutorService.submit()}} method can be used (in place of the {{execute()}} method) to submit a task to a thread pool and obtain a {{Future}} object. When the task is submitted via {{ExecutorService.submit()}}, thrown exceptions never reach the uncaught exception handler because the thrown exception is considered to be part of the return status and is consequently wrapped in an {{ExecutionException}} and rethrown by {{Future.get()}} \[ [Goetz 2006a|AA. References#Goetz 06]\].
Compliant Solution (Future<V> and submit())
...
Bibliography
...
[[API 2006AA. References#API 06] ] | Interfaces | ]]></ac:plain-text-body></ac:structured-macro> | <ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="92366984-7381-48c6-b7a7-fac813596f8d"><ac:plain-text-body><![CDATA[ |
[[Goetz 2006aAA. References#Goetz 06] ] | Chapter 7.3, Handling Abnormal Thread Termination ]]></ac:plain-text-body></ac:structured-macro> |
...