起因
在Java默认的线程池中执行的程序,如果程序产生异常导致线程池里面的线程死掉,完全没有任何信息抛出来,这个是个很可怕的事情,程序静默,从日志看不到任何有用信息。
解决办法
线程池一般有两种提交办法:通过execute和submit两种方式往线程池提交我们的任务。
- 如果是execute 这种可以通过继承线程池,然后处理:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolExecutor extends ThreadPoolExecutor {
public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
System.out.println("MyThreadPoolExecutor.afterExecute()");
if (t != null) {
System.out.println("Error msg:{}",t.getMessage());
}
}
}
2)如果是submit方式提交:
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Future<?> f = (Future<?>) r;
try {
f.get();
} catch (InterruptedException e) {
logger.error("线程池中发现异常,被中断", e);
} catch (ExecutionException e) {
logger.error("线程池中发现异常,被中断", e);
}
}
总结
最终采用如下的代码,可能不高效,但是异常都可以捕获到。
package threads;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyThreadExcutor extends ThreadPoolExecutor {
private static final Logger logger = LoggerFactory.getLogger(MyThreadExcutor.class);
public MyThreadExcutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t != null) {
logger.error("Find exception error reason :{}", t.getMessage());
}
Future<?> f = (Future<?>) r;
try {
f.get();
} catch (InterruptedException e) {
logger.error("线程池中发现异常,被中断", e);
} catch (ExecutionException e) {
logger.error("线程池中发现异常,被中断", e);
}
}
}