...
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="efeb5522-f498-4284-9bcb-0f8a3a8c461a"><ac:plain-text-body><![CDATA[ |
[[Goetz 2006aAA. References#Goetz 06] ] | Chapter 7.3, Handling Abnormal Thread Termination ]]></ac:plain-text-body></ac:structured-macro> |
...