概述
1:submit(Callable<T> task)
submit方便Exception处理:
There is a difference when looking at exception handling. If your tasks throws an exception and if it was submitted with execute this exception will go to the uncaught exception handler (when you don't have provided one explicitly, the default one will just print the stack trace to System.err). If you submitted the task with submit any thrown exception, checked or not, is then part of the task's return status. For a task that was submitted with submit and that terminates with an exception, the Future.get will rethrow this exception, wrapped in an ExecutionException.
意思就是如果你在你的task里会抛出checked或者unchecked exception,而你又希望外面的调用者能够感知这些exception并做出及时的处理,
那么就需要用到submit,通过捕获Future.get抛出的异常。
public interface ExecutorService extends Executor {
...省略
<T> Future<T> submit(Callable<T> task);
好在java.util.concurrent.ThreadPoolExecutor 预留了一个方法,运行在任务执行完毕进行扩展(当然也预留一个protected方法beforeExecute(Thread t, Runnable r)):
protected void afterExecute(Runnable r, Throwable t) { }
此方法的默认实现为空,这样我们就可以通过继承或者覆盖ThreadPoolExecutor 来达到自定义的错误处理。
解决办法如下:
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(11, 100, 1, TimeUnit.MINUTES, //
new ArrayBlockingQueue<Runnable>(10000),//
new DefaultThreadFactory()) {
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
printException(r, t);
}
};
private static void printException(Runnable r, Throwable t) {
if (t == null && r instanceof Future<?>) {
try {
Future<?> future = (Future<?>) r;
if (future.isDone())
future.get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null)
log.error(t.getMessage(), t);
}
为什么重写protected void afterExecute(Runnable r, Throwable t) { }方法就可以获取具体异常呢?
答:百度ThreadPoolExcutor源码解析
https://www.jianshu.com/p/96772777749b
或者不用重写该方法,直接在future.get()的时候 加上try catch
最后核心的是:
每个线程在执行的时候,都会把发生的异常catch住,然后 交给afterExecute(task, thrown); 如果重写了该方法,可以自行处理,如果没重写该方法,会向外抛出,在future.get()的时候 自行捕获即可。
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
public class ThreadPoolExecutor extends AbstractExecutorService {
...省略
protected void afterExecute(Runnable r, Throwable t) { }
最后
以上就是傻傻含羞草为你收集整理的捕获Java线程池执行任务抛出的异常 futrue获取结果异常情况的全部内容,希望文章能够帮你解决捕获Java线程池执行任务抛出的异常 futrue获取结果异常情况所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复