解决定时任务@Scheduled的阻塞问题

  • Post author:
  • Post category:其他


@Scheduled采用单线程处理定时任务,不同的定时任务之间相互交错执行,由于单线程的限制会出现不同的阻塞情况,直接在项目中添加如下配置类即可解决阻塞问题:

@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    /*如果采用注解@Asnyc的方式其默认线程池大小为100,会浪费资源*/
    @Bean
    public Executor taskExecutor() {
        //指定定时任务线程数量,可根据需求自行调节
        return Executors.newScheduledThreadPool(5);
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.setScheduler(taskExecutor());
    }
}

由于CPU核数的限制,存在时间片轮转竞争的问题,执行时间在物理意义上肯定会存在非常细微的差别,如果对时间要求非常非常非常严格比如作者公司有这样的情况:行方无时无刻都在将大量的数据写入当天的es中,如果当天es索引不存在则会导致部分数据写入上一天的es索引里,那么这里就存在索引创建时间与数据写入时间的一个先后问题,一点点的时间差就可能导致部分的数据丢失,由于作者公司对接银行所以这种情况是不允许发生的,所以针对这种特殊情况我用了一种特殊方法来处理,代码如下:

   //到每天的23小时59分的55秒开始执行这个任务
    @Scheduled(cron = "55 59 23 * * ?")
    public void task2(){
        //第二天的开始时间自己写个工具类实现
        String nextDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS").format(TimeUtils.getBeginDayOfTomorrow());
        while (true){
            String nowDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS").format(new Date());
            if(DateUtil.compareTime(nowDate,testBegin,"yyyy-MM-dd HH:mm:ss.SS")>=0){
                System.out.println("创建索引时间为:"+ nowDate);
                System.out.println("测试任务成功");
                break;
            }
        }
        System.out.println("测试退出成功");
   }

上一块代码这样写还有个坏处那就是零点前的这五秒由于死循环的原因会导致这个方法对cpu抢占非常高,如果不在乎这五秒的性能可以用,如果在乎这五秒的性能就不能用,不巧的是作者公司很在乎每一秒,所以最后还是采用了其他方法,方法是在配合第一个配置类,然后在每天零点前一个小时创建一个定时任务,提前把第二天的es索引创建起来,然后让同事在写数据的时候做另外一些改动。



版权声明:本文为qq_38485279原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。