本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
如今已经大量场景需使用线程池来处理任务,那么有没有考虑线程池中出现了异常,该怎么办?保证整个池子正常进行?那是抛弃异常的任务或线程吗?还是不处理?各种情况都会有怎样的结局??
本文举例模拟任务中出现异常,做不同的处理方式,验证不同的结果!
第一种情况:对异常不做任何处理!
任务类:
/**
* @Description : TODO 模拟任务执行过程中出现异常,且不做任何处理
* @Author : lixiunan
* @Date : 2021/7/20
**/
@Slf4j
public class NoneTask implements Runnable{
@Override
public void run() {
log.info("开始");
//时间戳摩2会有机会==1进入
if(System.currentTimeMillis() % 2 == 1){
//制造异常阻断程序正常执行
int i = 5/0;
log.info("异常了");
}else{
log.info("正常");
}
log.info("结束");
}
}
测试类
/**
* @Description : TODO 开启两个线程,每间隔5秒就重复执行一次任务
* @Author : lixiunan
* @Date : 2021/7/20
**/
public class TestScheduleException {
public static void main(String[] args) {
final int CORE_SIZE = 2;
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
new ScheduledThreadPoolExecutor(CORE_SIZE);
for (int i = 0; i < CORE_SIZE; i++) {
scheduledThreadPoolExecutor.scheduleWithFixedDelay(
new NoneTask(),1000,5000, TimeUnit.MILLISECONDS);
}
}
}
测试结果:
[pool-1-thread-1] INFO testException.NoneTask - 开始
[pool-1-thread-1] INFO testException.NoneTask - 正常
[pool-1-thread-1] INFO testException.NoneTask - 结束
[pool-1-thread-2] INFO testException.NoneTask - 开始
[pool-1-thread-2] INFO testException.NoneTask - 正常
[pool-1-thread-2] INFO testException.NoneTask - 结束
[pool-1-thread-1] INFO testException.NoneTask - 开始
[pool-1-thread-2] INFO testException.NoneTask - 开始
后果:
程序会卡住!并不结束!并不输出任何的信息!
第二种:throw抛出异常
任务类:
/**
* @Description : TODO 假设>5秒就是异常情况,并抛出异常
* @Author : lixiunan
* @Date : 2021/7/20
**/
@Slf4j
public class ThrowTask implements Runnable{
@SneakyThrows
@Override
public void run() {
log.info("开始");
int time = random();
if(time >= 5){//任务执行有异常 : 并显式地去抛出异常
throw new RuntimeException("任务执行超过五秒有异常");
}else {//任务执行正常
log.info("正常执行任务");
Thread.sleep(time*1000);
}
log.info("结束");
}
/**
* 随机生成1-10之间的数
* @return
*/
public int random(){
Random rand = new Random();
return rand.nextInt(10)+1;
}
}
测试类
/**
* @Description : TODO 开启两个线程,每间隔5秒就重复执行一次任务
* @Author : lixiunan
* @Date : 2021/7/20
**/
public class TestScheduleException {
public static void main(String[] args) {
final int CORE_SIZE = 2;
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
new ScheduledThreadPoolExecutor(CORE_SIZE);
for (int i = 0; i < CORE_SIZE; i++) {
scheduledThreadPoolExecutor.scheduleWithFixedDelay(
new ThrowTask(),1000,5000, TimeUnit.MILLISECONDS);
}
}
}
测试结果
[pool-1-thread-2] INFO testException.ThrowTask - 开始
[pool-1-thread-1] INFO testException.ThrowTask - 开始
[pool-1-thread-1] INFO testException.ThrowTask - 正常执行任务
[pool-1-thread-1] INFO testException.ThrowTask - 结束
[pool-1-thread-1] INFO testException.ThrowTask - 开始
后果:
程序会卡住!并不结束!并不输出任何的信息!
第三种情况:捕获异常
任务类
/**
* @Description : TODO 对执行的逻辑进行try包裹
* @Author : lixiunan
* @Date : 2021/7/20
**/
@Slf4j
public class CatchTask implements Runnable{
@SneakyThrows
@Override
public void run() {
log.info("开始");
try {
if(System.currentTimeMillis() % 2 == 1){
Thread.sleep(5000);
throw new RuntimeException("模拟异常");
}else{
log.info("正常执行");
Thread.sleep(1000);
}
}catch (RuntimeException e){
log.info("捕获到模拟异常");
}
log.info("结束");
}
}
测试类
/**
* @Description : TODO 开启两个线程,每间隔5秒就重复执行一次任务
* @Author : lixiunan
* @Date : 2021/7/20
**/
public class TestScheduleException {
public static void main(String[] args) {
final int CORE_SIZE = 2;
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
new ScheduledThreadPoolExecutor(CORE_SIZE);
for (int i = 0; i < CORE_SIZE; i++) {
scheduledThreadPoolExecutor.scheduleWithFixedDelay(
new CatchTask(),1000,5000, TimeUnit.MILLISECONDS);
}
}
}
测试结果
[pool-1-thread-1] INFO testException.CatchTask - 开始
[pool-1-thread-1] INFO testException.CatchTask - 正常执行
[pool-1-thread-2] INFO testException.CatchTask - 开始
[pool-1-thread-2] INFO testException.CatchTask - 正常执行
[pool-1-thread-1] INFO testException.CatchTask - 结束
[pool-1-thread-2] INFO testException.CatchTask - 结束
[pool-1-thread-1] INFO testException.CatchTask - 开始
[pool-1-thread-2] INFO testException.CatchTask - 开始
[pool-1-thread-1] INFO testException.CatchTask - 捕获到模拟异常
[pool-1-thread-1] INFO testException.CatchTask - 结束
[pool-1-thread-2] INFO testException.CatchTask - 捕获到模拟异常
[pool-1-thread-2] INFO testException.CatchTask - 结束
[pool-1-thread-1] INFO testException.CatchTask - 开始
[pool-1-thread-2] INFO testException.CatchTask - 开始
[pool-1-thread-2] INFO testException.CatchTask - 捕获到模拟异常
[pool-1-thread-2] INFO testException.CatchTask - 结束
[pool-1-thread-1] INFO testException.CatchTask - 捕获到模拟异常
[pool-1-thread-1] INFO testException.CatchTask - 结束
[pool-1-thread-2] INFO testException.CatchTask - 开始
[pool-1-thread-2] INFO testException.CatchTask - 正常执行
[pool-1-thread-1] INFO testException.CatchTask - 开始
[pool-1-thread-1] INFO testException.CatchTask - 正常执行
[pool-1-thread-1] INFO testException.CatchTask - 结束
[pool-1-thread-2] INFO testException.CatchTask - 结束
后果
程序会一直正常执行!并输出有异常时的信息!
总结
为避免线程池停止工作,为避免异常被吞,请手动捕获处理异常!