Bootstrap

【线程池】 ScheduledExecutorService (2) scheduleAtFixedRate任务挂掉但没有日志信息

项目中碰到一个问题,ScheduledExecutorService实例通过scheduleAtFixedRate起了一个定时循环的任务,发现这个任务终止了,但是又没有相关日志提示。

本文得出一个结论:
当某次执行该任务,若出现异常且没有try catch,不会打印任务异常日志,并且会终止后续的任务

我们来看下验证过程:
通过Runnable的run方法中抛出一个异常,查看是否继续打印日志,如果是没有日志继续打印,说明异常导致整个计划任务终止了。

捕获并处理异常

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduleExecutorServiceTest {
    public static void main(String[] args) {
        ScheduleExecutorServiceTest test = new ScheduleExecutorServiceTest();
        test.testAtFixedRate();
    }
    
    private ScheduledExecutorService executor;
    
    public ScheduleExecutorServiceTest() {
        executor = Executors.newScheduledThreadPool(4);
    }
    
    
    public void testAtFixedRate() {
        executor.scheduleAtFixedRate(new Runnable() {
            
            public void run() {
                System.out.println("执行主任务");
                try{
                    //抛出一个计算异常
                    long result = 2/0;
                }catch (Exception e){
                    System.out.println(e);
                }
             
            }
        }, 1000, 3000, TimeUnit.MILLISECONDS);

    }}
    

上文中抛出的异常已经被处理,我们看下结果:

执行主任务
java.lang.ArithmeticException: / by zero
执行主任务
java.lang.ArithmeticException: / by zero

上述结果表明按预期间隔3s打印了执行信息,说明捕获异常后,不影响下一个任务的触发

未捕获异常

下面我们模拟下如果不try catch 异常的场景,注释掉上文中的try catch语句:

 public void run() {
                System.out.println("执行主任务");
             //   try{
                    long result = 2/0;
//                }catch (Exception e){
//                    System.out.println(e);
//                }
             
            }
        }, 1000, 3000, TimeUnit.MILLISECONDS);

我们再看下结果:

执行主任务

日志发现打印的内容只打印了一遍,说明只执行了一次就挂了,后续的任务不再触发;且没有任何异常日志输出。因此,我们格外需要注意,尽量捕获异常,避免没有错误日志,导致无法定位问题。

;