大家好,我是小趴菜,关于线程池我们都听过,也可能用过,也有了解过底层源码实现的,但是今天不研究它的实现原理,我们来看一下,提交到线程池的任务如果有异常了,会有什么问题
案例实现
首先我们定义一个线程池,
js
private static final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 2, 10,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(1),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
System.out.println("创建了线程===============================");
t.setName("xpc-------------");
return t;
}
});
然后定义一个任务的实现,让这个任务会抛出异常
js
static class Task implements Runnable{
@Override
public void run() {
int i = 1/0;
}
}
定义一个main方法测试
js
public static void main(String[] args) throws Exception{
for(int i = 0 ; i < 500000; i ++){
threadPool.execute(new Task());
Thread.sleep(100);
}
threadPool.shutdown();
}
你会发现,如果整个任务有异常,你会发现会不断的创建线程
我们使用线程池的原因就是因为线程池可以复用线程,来解决不断创建线程,然后销毁线程的消耗
因为整个线程执行过程中出现异常,整个线程就中止了,所以下一个任务进来以后就会重新创建一个线程来执行整个任务
创建线程,销毁线程都是需要消耗资源的,所以必然会对服务器造成一定的压力
解决办法
把我们的任务类修改一下,用try{}catch(){}把我们的业务代码包裹起来
js
static class Task implements Runnable{
@Override
public void run() {
try{
int i = 1/0;
}catch (Exception e) {
//在这里处理异常,比如业务补偿等,或者打印日志,等待人工处理
System.out.println("任务执行异常了");
return;
}
}
}
main方法
js
public static void main(String[] args) throws Exception{
for(int i = 0 ; i < 500000; i ++){
threadPool.execute(new Task());
}
threadPool.shutdown();
}
你可以发现,就创建了两个线程,因为我们线程池设置的最大线程数就是两个,就避免了不断的创建线程整个问题