经典面试题:线程池提交任务,发生异常,你是怎么处理的?
发布于 2021-09-07 11:34 ,所属分类:2021面试经验技巧分享
前言
大家好,我是程序员田螺,今天我们来看一道特别经典的面试题:线程池中的线程,提交新任务,发生异常时,你是如何处理的?
1.当提交新任务时,异常如何处理呢?
我们先来看一段代码:
ExecutorServicethreadPool=Executors.newFixedThreadPool(5);
for(inti=0;i<5;i++){
threadPool.submit(()->{
System.out.println("currentthreadname"+Thread.currentThread().getName());
Objectobject=null;
System.out.print("result##"+object.toString());
});
}
显然,这段代码会有异常,我们再来看看运行结果

虽然没有结果输出,但是也没有抛出异常,所以我们无法感知任务出现了异常,所以需要添加try/catch。如下图:
因此,线程的异常处理,我们可以直接try...catch捕获。
2. 线程池exec.submit()的执行流程
通过debug上面有异常的submit方法(建议大家也去debug看一下,下图的每个方法内部是我打断点的地方),处理有异常submit方法的主要执行流程图如下:

//构造feature对象
/**
*@throwsRejectedExecutionException{@inheritDoc}
*@throwsNullPointerException{@inheritDoc}
*/
publicFuture<?>submit(Runnabletask){
if(task==null)thrownewNullPointerException();
RunnableFuture<Void>ftask=newTaskFor(task,null);
execute(ftask);
returnftask;
}
protected<T>RunnableFuture<T>newTaskFor(Runnablerunnable,Tvalue){
returnnewFutureTask<T>(runnable,value);
}
publicFutureTask(Runnablerunnable,Vresult){
this.callable=Executors.callable(runnable,result);
this.state=NEW;//ensurevisibilityofcallable
}
publicstatic<T>Callable<T>callable(Runnabletask,Tresult){
if(task==null)
thrownewNullPointerException();
returnnewRunnableAdapter<T>(task,result);
}
//线程池执行
publicvoidexecute(Runnablecommand){
if(command==null)
thrownewNullPointerException();
intc=ctl.get();
if(workerCountOf(c)<corePoolSize){
if(addWorker(command,true))
return;
c=ctl.get();
}
if(isRunning(c)&&workQueue.offer(command)){
intrecheck=ctl.get();
if(!isRunning(recheck)&&remove(command))
reject(command);
elseif(workerCountOf(recheck)==0)
addWorker(null,false);
}
elseif(!addWorker(command,false))
reject(command);
}
//捕获异常
publicvoidrun(){
if(state!=NEW||
!UNSAFE.compareAndSwapObject(this,runnerOffset,
null,Thread.currentThread()))
return;
try{
Callable<V>c=callable;
if(c!=null&&state==NEW){
Vresult;
booleanran;
try{
result=c.call();
ran=true;
}catch(Throwableex){
result=null;
ran=false;
setException(ex);
}
if(ran)
set(result);
}
}finally{
//runnermustbenon-nulluntilstateissettledto
//preventconcurrentcallstorun()
runner=null;
//statemustbere-readafternullingrunnertoprevent
//leakedinterrupts
ints=state;
if(s>=INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
通过以上分析,submit执行的任务,可以通过Future对象的get方法接收抛出的异常,再进行处理。我们再通过一个demo,看一下Future对象的get方法处理异常的姿势,如下图:

因此,可以使用这两种方案处理线程池异常:
1.在任务代码try/catch捕获异常, 2.通过Future对象的get方法接收抛出的异常
3. 为工作者线程设置UncaughtExceptionHandler,在uncaughtException方法中处理异常
也可以为工作者线程设置UncaughtExceptionHandler,在uncaughtException方法中处理异常,我们直接看这样实现的正确姿势:
ExecutorServicethreadPool=Executors.newFixedThreadPool(1,r->{
Threadt=newThread(r);
t.setUncaughtExceptionHandler(
(t1,e)->{
System.out.println(t1.getName()+"线程抛出的异常"+e);
});
returnt;
});
threadPool.execute(()->{
Objectobject=null;
System.out.print("result##"+object.toString());
});
运行结果:
4.重写ThreadPoolExecutor的afterExecute方法,处理传递的异常引用
这是jdk文档的一个demo:
classExtendedExecutorextendsThreadPoolExecutor{
//这可是jdk文档里面给的例子。。
protectedvoidafterExecute(Runnabler,Throwablet){
super.afterExecute(r,t);
if(t==null&&rinstanceofFuture<?>){
try{
Objectresult=((Future<?>)r).get();
}catch(CancellationExceptionce){
t=ce;
}catch(ExecutionExceptionee){
t=ee.getCause();
}catch(InterruptedExceptionie){
Thread.currentThread().interrupt();//ignore/reset
}
}
if(t!=null)
System.out.println(t);
}
}}
5. 因此,被问到线程池异常处理,如何回答?

--end--
求点赞、在看、转发,感谢


![[JAVA面试题] 传智博客Java就业班面试资料java面试题(程序猿面试技巧+常见笔试题分析) 六讲](https://static.kouhao8.com/sucaidashi/xkbb/78347caafea46f36a69b5d05ca66ad05.png?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)
![[就业指导] Java面试题专属视频 最新Java阿里京东美团滴滴java面试题及答案教程](https://static.kouhao8.com/sucaidashi/xkbb/be2bcf6c23bac0005fdd61e16024bd9c.png?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)



![[JAVA面试题] Java BAT大型公司面试专属必备技能视频教程](https://static.kouhao8.com/sucaidashi/xkbb/faf2918ea254fd9be00db2eca82f6b78.png?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)

![[就业指导] Java面试题视频找工作不用愁](https://static.kouhao8.com/sucaidashi/xkbb/979e2e0a2e6f5a53ab3c1bff94ed0e20.jpg?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)



![[就业指导] Java面试专属视频 最新Java阿里京东美团滴滴面试题及答案教程](https://static.kouhao8.com/sucaidashi/xkbb/fb2f88633d9be374ae995992b13e7779.jpg?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)
![[java面试题] 尚硅谷1024程序员福利之java学科新增面试宝典视频教程](https://static.kouhao8.com/sucaidashi/xkbb/f5826c371702bac5fb45b06bb7c24342.png?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)




![JAVA面试题] 极客JavaWeb工程师全套视频教程 (初级+中级+高级) 一共485集 送面试辅导](https://static.kouhao8.com/sucaidashi/xkbb/439729a81224e1d2bd719383b03cd0dc.png?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)
![[就业指导] 2017最新IOS面试必看题教程 尚学堂 iOS面试题 视频教程 教学视频](https://static.kouhao8.com/sucaidashi/xkbb/49649e1f340e7901b2b85424b87b24d4.png?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)
![[Python] Python实战视频教程 基于Python项目与面试题讲解-Python核心技术进阶训练篇](https://static.kouhao8.com/sucaidashi/xkbb/ca6c1f3f4d1532b281ecdc1542c96831.jpg?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)


![[项目实战] Python实战视频教程 Python核心技术进阶训练篇 基于Python项目与面试题](https://static.kouhao8.com/sucaidashi/xkbb/cce0cbfcce42787e572f6df16e475cc9.jpg?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)

![[项目实战] Python实战视频教程 Python核心技术进阶训练篇 基于Python项目与面试题讲解](https://static.kouhao8.com/sucaidashi/xkbb/110e0fb426046bcd7b8eeef1cdf23231.png?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)
![[iOS] 极客学院 高级编程课程视频 iOS开发工程师 全程培养计划 9.2G 讲解必会面试题](https://static.kouhao8.com/sucaidashi/xkbb/fed110993a9d98e708b2a116de6749bc.jpg?x-oss-process=image/format,webp/resize,w_88/crop,w_88,h_88,g_nw)
相关资源