服务器定时任务不执行-服务器设置定时重启-第1张图片在SpringBoot中,您能够根据@Scheduled注解界定一个生产调度每日任务,可是有时候您也许会发觉一些生产调度每日任务并并不是与此同时实行的,而是否每一次都实行。这是什么原因?

下列编码界定了每十秒实行一次的任务计划:

@Componentpublic class ScheduledTaskDemo { private static final Logger logger = LoggerFactory.getLogger(ScheduledTaskDemo.class); @Scheduled(cron = "0/10 * * * * *") public void execute() { logger.info("Scheduled task is running... ..."); }}

这时,当您运行SpringBoot应用软件时,您能见到这一方案的每日任务每10秒在操纵台子上打印出一个日志。

2017-12-21 22:20:20.832 INFO 7424—[main]s . b . c . e . t . tomcatembeddeservletcontainer:Tomcat在端口号上运行:8000(http)2017-12-21 22:20:20.859 INFO 7424—[main]com . example . demo . demo application:在12.134秒内运行demo application(JVM运作14.155

但都还没完毕。

要是没有表明有关日志,请查验@EnableScheduling注解是加入到内容类或是配备类。

在上面的一些编码中,大家应用cron关系式来特定生产调度每日任务的实行时间点,即从0秒到每10秒。如今大家加上另一个任务计划:

@Componentpublic class SecondScheduledTaskDemo { private static final Logger logger = LoggerFactory.getLogger(ScheduledTaskDemo.class); @Scheduled(cron = "0/10 * * * * *") public void second() { logger.info("Second scheduled task is starting... ..."); logger.info("Second scheduled task is ending... ..."); }}

如今运行SpringBoot应用软件,随后查询日志:

2017-12-21 23:12:20.007 INFO 13208—[pool-1-thread-1]c . e . demo . scheduled . scheduled task demo:第一个任务计划已经逐渐… … 2017-12-21 23:12:35.013 INFO 13208—[pool-1-thread-1]c . e . demo . scheduled task demo:第一个任务计划已经完毕……2017-12-21 c . e . demo . scheduled . scheduled task demo:第一个任务计划将要完毕……2017-12-21 23:12:55.002 INFO 13208—[pool-1-thread-1]c . e . demo . scheduled . Second scheduled task demo:第二个任务计划即将开始……2017-12-21 23:12:55.002 INFO 13208—[pool-1-thread-1]c . e . demo . Second scheduled

留意日志中计划任务的实施時间。第二个计划任务应当每10秒实行一次,可是从23:12:20到23:13:55应当实行了四次,可是只实行了2次。

cron表述不对吗?

为了更好地找到缘故,大家从@Scheduled注解的源码逐渐:

* *

对{@code @Scheduled}注解的正确处理是根据*申请注册{ @ link scheduledannocationbeanstreactor }来实行的。这能够*手动式开展,或是更社交媒体化地,根据{@ code} *原素或@ {@ link enable scheduling}注解开展。*突显,每一个含有@Scheduled注解的办法都将被申请注册为Scheduled annotationbeanstallCPU,随后往下查询Scheduled annotationbeanstallCPU:

/** * Set the {@link org.springframework.scheduling.TaskScheduler} that will invoke * the scheduled methods, or a {@link java.util.concurrent.ScheduledExecutorService} * to be wrapped as a TaskScheduler. *

假如未找到,将运用默认设置的生产调度程序流程分析:在前后文中检索*唯一的{@link TaskScheduler} bean,不然检索名叫“TaskScheduler”的{ @ link TaskScheduler } * bean一样的搜索也将对* a { @ link ScheduledExecutorService } bean实行。假如两者都不可分析,*将在注册器中建立当地单核默认设置生产调度程序流程。* @参照# DEFAULT _ TASK _ SCHEDULER _ BEAN _ NAME */public void setScheduler(目标生产调度程序流程){ this.scheduler = scheduler}关键来啦,留意这样的话:

假如两者都不可分析,将在注册器中建立当地单核默认设置生产调度程序流程。

这样的话的意思是,如果我们不主动配备大家必须的线程同步器,Spring Boot会正常应用单核生产调度器来解决大家用@Scheduled注解完成的调整每日任务,因此我们可以了解刚刚的难题:

23:12:20,第一个生产调度每日任务逐渐在线程池-1-thread-1中实行。因为大家沒有配备生产调度器,现阶段这一线程池池-1中只有一个进程,这一进程在打印出运行日志后逐渐休眠状态。第二个任务计划早已准备好实行了,可是线程池中沒有过多的进程,因此大家只有等候。

23:12:30,第一个预订每日任务仍在休眠状态,第二个预订每日任务还等待。

23:12:35,第一个预订任务完成休眠状态,完毕日志打印出结束。这时,线程池/实行后,线程池空空余。

23:12:40,线程池/

一定要注意,依据cpu的不一样,这儿还可以实行第二个任务计划。

… …

了解了这一全过程以后,就非常容易处理这个问题了。

依据刚刚手记中的叙述,大家只必须给予一个合乎大家要求的TaskScheduler,并在前后文中申请注册就可以。

@Configurationpublic class ScheduledTaskConfiguration implements SchedulingConfigurer { /** * Callback allowing a {@link TaskScheduler * TaskScheduler} and specific {@link Task Task} * instances to be registered against the given the {@link ScheduledTaskRegistrar} * * @param taskRegistrar the registrar to be configured. */ @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { final ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); taskScheduler.setPoolSize(2); taskScheduler.initialize(); taskRegistrar.setTaskScheduler(taskScheduler); }}

上边的编码给予了一个线程池尺寸为2的线程同步器。从现在起跳一跳看实际效果。

2017-12-21 23:28:30.001 INFO 7972—[tasksscheduler-1]c . e . demo . scheduled . scheduledtaskdemo:第二个任务计划开始了… … 2017-12-21 23:28:30.001 INFO 7972—[tasksscheduler-2]c . e . demo . scheduled . scheduled . desmo:第一个任务计划开始了……2017-12-21 23:28:30

能够看得出,当线程池中有两个进程时,这两个计划任务是依据预订時间开启的,并不互相影响。

评论(0条)

刀客源码 游客评论