你能帮我验证这段代码吗?我正在尝试同时执行一些文件下载任务。以后如果所有下载都成功,那么我想对它们进行后期处理。如果任何任务失败,我应该向调用者抛出异常,因为我不想发布半成功结果。
这是我的自定义ThreadPoolExecutor,我尝试检查池中任何线程的任何异常
public class CustomExecutorePool extends ThreadPoolExecutor {
private AtomicBoolean errorFlag = new AtomicBoolean(false);
public CustomExecutorePool(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
}
@Override
protected void afterExecute(Runnable r, Throwable childThreadException){
if(null != childThreadException){
logger.error("Exception occurred in one of the child threads: >>> " + childThreadException.getMessage() );
errorFlag.set(true);
}
}
public AtomicBoolean isErrorPresent(){
return errorFlag;
}
如您所见,我尝试使用AtmociBoolean标志,并在任何子线程有异常时将其设置为true。
这是我主要课程的片段,我尝试使用这些信息:
ThreadPoolExecutor docFetchingThreadPool = new CustomExecutorePool(...)
try {
// populate the thread pool queue for all the runnables to fetch documents
for(Document myDoc : list){
docFetchingThreadPool.execute(myDoc);
}
logger.info("All docs added to the work queue");
docFetchingThreadPool.shutdown();
logger.info("Waiting to finish work queue task for 3 mins");
docFetchingThreadPool.awaitTermination(3, RETREIVAL_WAIT_UNIT);
if(docFetchingThreadPool.isTerminated() &&
!(docFetchingThreadPool.isErrorPresent().get()){
//sucessfull post-process all docs now
//......
}else {
throw new MyException("Exception occured in fetching");
}
} catch (InterruptedException e) {
logger.error("Interrupt exception received ", e);
Thread.currentThread().interrupt();
throw new MyException("Interrupt exception");
} finally {
if(null != docFetchingThreadPool){
logger.info("Force shoutdown for residual threads if any...");
docFetchingThreadPool.shutdownNow();
}
}
如果这看起来不错,请告诉我,或者错误布尔标志是否会出现任何同步问题,或者这是否是正确的方法。 我知道在执行程序服务上使用invokeall函数,但仍然在争论哪一个将是一个更清晰的方法来处理任何异常情况。
感谢您的时间,
答案 0 :(得分:1)
你不应该将ThreadPoolExecutor子类化。特别是,这使得线程池仅可用于执行一组任务。
当您向线程池提交任务时,您将从线程池中获得Future
。所以你只需要遍历返回的期货,get()
他们的结果,如果任何get方法抛出ExecutionException(意味着任务本身抛出异常,包含在ExecutionException中),你可以做任何你想做的事。 / p>