以下文章来自ArchitectMustHave1.ScheduledThreadPoolScheduledThreadPool是JDK自带的一个类,可以用来代替Timer类实现定时任务。一个Timer只能执行一个任务,而一个ScheduledThreadPool可以同时执行多个定时任务。用法很简单,直接看例子:publicclassScheduledThreadPoolService{privateLoggerlogger=LoggerFactory.getLogger(getClass().getSimpleName());//参数表示可以同时执行的计划任务个数timeprivateScheduledExecutorServiceservice=Executors.newScheduledThreadPool(3);/**schedule:执行任务,延时2秒*/publicvoidtask0(){service.schedule(()->{logger.info("task0-start");sleep(2);logger.info("task0-end");},2,TimeUnit.SECONDS);}/**scheduleAtFixedRate:2秒后,每4秒执行一次任务。注意,如果任务的执行时间(比如6秒)大于间隔时间,就会等待任务完成,直接开始下一个任务*/publicvoidtask1(){service.scheduleAtFixedRate(()->{logger.info("task1-start");sleep(2);logger.info("task1-end");},2,4,TimeUnit.SECONDS);}/**scheduleWithFixedDelay:2秒后,每次延时4秒执行一个任务注意,这里是等待上次任务执行结束,然后延时固定时间后开始下一个任务*/publicvoidtask2(){service.scheduleWithFixedDelay(()->{logger.info("task2-start");sleep(2);logger.info("task2-end");},2,4,TimeUnit.SECONDS);}privatevoidsleep(长时间){try{TimeUnit.SECONDS.sleep(time);}catch(InterruptedExceptione){e.printStackTrace();}}}类似于线程池的使用。它还使用Executors类来创建ScheduledThreadPool。在常用方法的例子中有说明。使用ScheduledThreadPool即可实现简单的定时任务,无需引入其他依赖。挺方便的_java培训2.@Scheduled@Scheduled是Spring框架的定时任务实现,比JDK的ScheduledThreadPool更强大。可以先创建一个SpringBoot工程,在启动类中添加@EnableScheduling注解使@Scheduled生效,启动定时任务:@SpringBootApplication@EnableSchedulingpublicclassLearnSpringbootApplication{publicstaticvoidmain(String[]args){SpringApplication.run(LearnSpringbootApplication.class,args);}}然后定义任务类,用@Scheduled配置具体的定时规则:**fixedRate:每2秒执行一次任务。注意,默认情况下,定时任务是在同一个线程中同步执行的。如果任务执行时间(比如6秒)大于间隔时间,则等待任务执行结束,直接开始下一个任务*/@Scheduled(fixedRate=2000)publicvoidtask0(){logger.info("task0-start");sleep(6);logger.info("task0-end");}/**fixedDelay:每次延迟2每秒执行一次任务注意这里是等待为上一个任务执行结束,然后在固定时间延迟后开始下一个任务*/@Scheduled(fixedDelay=2000)publicvoidtask1(){logger.info("task1-start");sleep(6);logger.info("task1-end");}/**initialDelay:第一个任务开始的延迟时间*/@Scheduled(initialDelay=2000,fixedDelay=3000)publicvoidtask2(){logger.info("task2-start");sleep(6);logger.info("task2-end");}privatevoidsleep(longtime){try{TimeUnit.SECONDS.sleep(time);}catch(InterruptedExceptione){e.printStackTrace();}}fixedRate、fixedDelay、initialDelay属性的时间单位是毫秒,使用比较简单。请参考代码Note这里重点介绍使用@Scheduled的cron属性来定义定时任务的时间表达式,功能比较多。先看一个简单的例子:@ServicepublicclassScheduleService{......./**每晚23:59执行一次*/@Scheduled(cron="05923?")publicvoidtask3(){logger.info("task3-start");sleep(6);logger.info("task3-end");}..................}Next,看一下时间表达式对应的cron属性的定义规则:1.依次为:秒、分、时、日、月、周,用空格隔开2、月、周可以用数字或英语单词的前三个字母。3.day和week可能会冲突,所以两者可以配置为?4、常用通配符的含义:表示任意值,比如设置在second字段上,表示每秒触发一次?表示不指定任何值,只能出现在day或week的位置,用于处理day和week之间可能发生的冲突。比如2020年8月15日是星期六,如果在周的位置指定为星期一,就会出现冲突导致定时任务失败。如果我们不关心一天或一周的时间,我们也可以将它设置为?-表示时间间隔,比如在秒上设置1-3,表示第一、二、三秒触发/表示时间间隔,比如在秒上设置2/4表示每4秒触发一次seconds从第2秒开始,表示枚举多个值,例如MON,WED,FRI表示周一、周三、周五触发。5.几个表达式的例子:009?:每天早上9点触发00/30*?:每30分钟触发03018?*周一至周五:触发010121,15*?每周一至周五18:30:触发00/107-81,15*?每月1、15日12:10:每月1、15日早上7:00-8:00每10分钟触发一次。6.注意不同版本的Spring支持不同的cron属性。例如,较新版本中的cron属性仅支持6个字段。包括年份;同时不支持#、L、W通配符。7.注意@Scheduled默认会使用同一个线程同步执行所有的定时任务。要打破这一点,可以在SpringBoot启动类上配置@EnableAsync注解使异步线程可用,然后在定时任务方法上配置@Async注意,异步线程会被用来执行定时任务。3.Quartz除了上面的方法,我们还有一个更好的选择,那就是Quartz。在SpringBoot中集成Quartz,需要先添加如下Maven依赖:org.springframework.bootspring-boot-starter-quartz2.3.2.RELEASE和@S??cheduled一样,也需要在启动类中加上@EnableScheduling注解来启动定时任务:@SpringBootApplication@EnableSchedulingpublicclassLearnSpringbootApplication{publicstaticvoidmain(String[]args){SpringApplication.run(LearnSpringbootApplication.class,args);}}这样准备工作就完成了。接下来,我们来了解几个重要的概念:Job:定义要执行的具体任务。JobDetail:配置待执行任务的描述信息,即如何定位待执行的Job。每执行一次任务,都会根据JobDetail创建一个Job对象,避免并发执行任务时访问同一个Job对象导致的问题。Trigger:触发器,配置任务执行的时间规则,需要关联一个JobDetail。Scheduler:调度器,维护了JobDetail和Trigger的注册。当任务关联触发器到达预定时间时,调度器会执行task_java训练机构接下来,定时任务会通过Quartz实现,可以按照以上重要概念的顺序完成。1.定义Job定义Job有两种方式。第一种是直接定义任务类,注册到SpringIoC容器中:@ServicepublicclassQuartzJob{privateLoggerlogger=LoggerFactory.getLogger(getClass().getSimpleName());publicvoidhello(){logger.info("job0-start");Utils.sleep(TimeUnit.SECONDS,4);logger.info("job0-end");}}二是继承QuartzJobBean,重写exe??cuteInternal方法,该方法可以接受JobDetail传递的参数:start");Utils.sleep(TimeUnit.SECONDS,4);//获取参数JobDataMapjobDataMap=jobExecutionContext.getMergedJobDataMap();Stringdate=jobDataMap.getString("date");logger.info("参数:"+日期);logger.info("job1-end");}}这将JobDetail与我们之前定义的QuartzJob相关联。2、配置JobDetailJobDetail可以使用MethodInvokingJobDetailFactoryBean或者JobDetailFactoryBean配置,配置工作需要在一个Spring配置类中完成,可以定义一个QuartzConfig配置类,首先看MethodInvokingJobDetailFactoryBean的使用:@ConfigurationpublicclassQuartzConfig{@BeanpublicMethodInvokingJobDetailFactoryBeanmethodInvokingJobDetailFactoryBean(){MethodInvokingJobDetailFactoryBeanbean=newMethodInvokingJobDetailFactoryBean();//SpecifytheBeannameofthetaskclassintheIoCcontainerbean.setTargetBeanName("quartzJob");//Specifythemethodnametobeexecutedbean.setTargetMethod("hello");returnbean;}}AssociateJobDetailwiththetasksdefinedbyQuartzJobbefore,andthenlookatJobDetailFactoryBean:@ConfigurationpublicclassQuartzConfig{@BeanpublicJobDetailFactoryBeanjobDetailFactoryBean(){JobDetailFactoryBeanbean=newJobDetailFactoryBean();//Specifythetaskclassnamebean.setJobClass2(class);//PreparetheparameterJobDataMapjobDataMap=newJobDataMap();jobDataMap.put("date","2020-8-16");//Passtheparameterbean.setJobDataMap(jobDataMap);returnbean;}}AssociateJobDetailwiththepreviouslydefinedQuartzJob2andpassparameters.3.配置TriggerTrigger也是在QuartzConfig配置类中定义的。常用的Trigger有SimpleTrigger、CronTrigger等,可以分别通过SimpleTriggerFactoryBean和CronTriggerFactoryBean进行配置。我们首先使用SimpleTriggerFactoryBean配置的触发器关联MethodInvokingJobDetailFactoryBean配置的JobDetail:@ConfigurationpublicfigclassQuartz{@BeanpublicSimpleTriggerFactoryBeansimpleTriggerFactoryBean(){SimpleTriggerFactoryBeanbean=newSimpleTriggerFactoryBean();bean.setRepeatCount(10);bean.setRepeatInterval(2000);//关联JobDetailbean.setJobDetail(methodInvokingJobDetail)(anget);be}}SimpleTriggerFactoryBean使用起来比较简单然后使用CronTriggerFactoryBean配置的触发器关联JobDetailFactoryBean配置的JobDetail:@ConfigurationpublicclassQuartzConfig{@BeanpublicCronTriggerFactoryBeancronTriggerFactoryBean(){CronTriggerFactoryBeanbean=newCron"00beansetBean(););//关联JobDetailbean.setJobDetail(jobDetailFactoryBean().getObject());returnbean;}}CronTriggerFactoryBean在Spring中可以实现类似@Scheduledcronexpression的功能也支持年4的配置,配置Scheduler的最后一步是通过SchedulerFactoryBean配置Scheduler注册Trigger@ConfigurationpublicclassQuartzConfig{@BeanpublicSc??hedulerFactoryBeanschedulerFactoryBean(){SchedulerFactoryBeanbean=新的SchedulerFactoryBean();//注册两个Triggerbeans.setTriggers(simpleTriggerFactoryBean().getObject(),cronTriggerFactoryBean().getObject());returnbean;}}Quartz会使用异步线程来执行定时任务,不会出现像@Scheduled这样的定时任务在同一个线程中同步执行的情况。至此,SpringBoot集成Quartz的整个过程就完成了,运行项目可以看到定时任务按照预期的效果执行了。