当前位置: 首页 > 后端技术 > Java

SpringBoot多个定时器冲突,如何解决?

时间:2023-04-02 01:24:01 Java

战术分析上一篇博客忽略了定时器的一大重点……实际开发项目中肯定不止一个定时器,需要在很多场景下使用,多个定时器带来的问题:如何避免多个定时器相互冲突。推荐一个SpringBoot基础教程和实例:https://github.com/javastacks...使用场景我们的订单服务一般都有一个订单要支付,这个支付订单是有时间限制的,比如阿里巴巴的订单是5天,淘宝的订单是1天,拼多多的订单是1天,美团的订单是15分钟...资金系统中,如何同时更新多个存储分区中的资金信息...总的来说,实际开发的时候controller需要解决多个timer同时并发的问题,还要解决timer之间的冲突问题。问题不大。说到并发,就离不开多线程……看一看,问题就明白了。场景重现我们可以清楚的看到执行结果都是scheduling-1,所以可以确定是Springboot定时器默认是单线程的,但是问题来了。如果一个线程在线程竞争资源后执行时间很长,那么其他定时器怎么办,只能进入等待状态,时间越长,需要等待的定时器越多,这很容易导致雪崩……其实只需要添加一个配置类,然后添加注解即可解决问题。添加注解的具体代码如下:importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.scheduling.annotation.Async;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.stereotype.Component;importjava.text.SimpleDateFormat;importjava.util.Date;@ComponentpublicclassSchedulerTaskController{privateLoggerlogger=LoggerFactory.getLogger(SchedulerTaskController.class);privatestaticfinalSimpleDateFormatdateFormat=newSimpleDateFormat("HH:mm:ss");私人整数计数=0;@Scheduled(cron="*/6****")@Async("threadPoolTask??Executor")publicvoidprocess(){logger.info("English:thisisschedulertaskrunning"+(count++));}@Scheduled(fixedRate=6000)@Async("threadPoolTask??Executor")publicvoidcurrentTime(){logger.info("中文:当前时间"+dateFormat.format(newDate()));}}配置类具体代码如下:importorg.springframework.context.annotation.Bean;导入org.springframework.context.annotation.Configuration;导入org.springframework.scheduling.annotation.EnableAsync;导入org.springframework.scheduling.concurrent.ThreadPoolTask??Executor;导入java.util.concurrent。ThreadPoolExecutor;/**在使用多线程的时候,往往需要创建Thread类或者实现Runnable接口,如果我们要使用线程池,还需要创建Executors*在spring的使用中,我们已经给了我们很好的支持只要@EnableAsync就可以使用多线程*spring提供的ThreadPoolTask??Executor可以使用线程池*///@Configuration表示这个类是一个配置类@Configuration@EnableAsync//所有时序任务放在一个线程池中,定时任务启动时使用不同的线程。公共类TaskScheduleConfig{privatestaticfinalintcorePoolSize=10;//默认线程数privatestaticfinalintmaxPoolSize=100;//最大线程数privatestaticfinalintkeepAliveTime=10;//允许线程空闲时间(单位:默认秒),十秒后关闭线程privatestaticfinalintqueueCapacity=200;//缓冲区队列数privatestaticfinalStringthreadNamePrefix="it-is-threaddemo-";//线程池名称前缀@Bean("threadPoolTask??Executor")//bean的名称,默认为方法名首字母小写publicThreadPoolTask??ExecutorgetDemoThread(){ThreadPoolTask??Executorexecutor=newThreadPoolTask??Executor();executor.setCorePoolSize(corePoolSize);executor.setMaxPoolSize(maxPoolSize);executor.setQueueCapacity(keepAliveTime);setKeepAliveSeconds(queueCapacity);executor.setThreadNamePrefix(threadNamePrefix);//线程池拒绝任务的处理策略executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy());//初始化executor.initialize();回归执行人;}}然后我们可以清楚的看到:如上,也解决了使用多线程解决Springboot多定时器冲突的问题版权声明:本文为CSDN博主《Wakandaforever》原创文章,遵循CC4.0BY-SA版权协议。转载请附上原文出处链接及本声明