当前位置: 首页 > 科技观察

SpringBoot下定时任务的使用方法大揭秘

时间:2023-03-13 00:09:49 科技观察

本文旨在用通俗易懂的语言讲述枯燥的知识。定时任务作为一种系统调度工具,广泛应用于一些需要定时作业的系统中,比如每隔一定时间点击统计,在未来的某个时间点执行某些动作……定时任务提供了相应的API供开发者调用主流开发语言。在Java中,有很多种实现定时任务的方法。原生方式实现一个完整的定时任务需要两个类,Timer和TimerTask。Timer是一个定时器类,用于启动后台线程按计划执行指定的任务。TimerTask是一个抽象类,它的子类代表一个可以被Timer调度的任务。另外,也可以使用ScheduledExecutorService类或者使用第三方jar库Quartz,其中Quartz是一个优秀的定时任务框架,目前已经非常成熟,使得其他的大部分核心思想或者底层定时任务框架来自Quartz。springboot作为Java的开发框架,在springboot项目中不仅可以使用Java提供的native方法实现定时任务,还可以使用springboot提供的定时任务API。下面,小编将Java原生和springboot方式实现所有的定时任务做一个整合。文章大纲:1.使用线程2.使用Timer类3.使用ScheduledExecutorService类4.使用Quartz5。使用spring的@Scheduled注解6.cron表达式1.线程实现使用线程设置休眠时间可以实现简单的定时任务逻辑。publicstaticvoidmain(String[]args){//定时任务间隔intsleepTime=2*1000;newThread(newRunnable(){@Overridepublicvoidrun(){while(true){try{System.out.println("线程方式执行一个定时Task");//线程休眠指定时间Thread.sleep(sleepTime);}catch(InterruptedExceptione){e.printStackTrace();}}}}).start();}2.Timer类Timer类允许调度TimerTask任务。使用此方法允许您的程序以特定频率执行。publicstaticvoidmain(String[]args){intsleepTime=2*1000;TimerTasktimerTask=newTimerTask(){@Overridepublicvoidrun(){System.out.println("定时器模式执行定时任务");}};newTimer().schedule(timerTask,1,sleepTime);}3.ScheduledExecutorService类ScheduledExecutorService是一个基于线程池设计的定时任务类,每个定时任务都会分配给线程池中的一个线程去执行,也就是执行任务并发互不影响。因此,基于ScheduledExecutorService类的定时任务类最终是基于线程调度实现的。publicstaticvoidmain(String[]args){intsleepTime=2*1000;ScheduledExecutorServicescheduledExecutor=Executors.newSingleThreadScheduledExecutor();scheduledExecutor.scheduleAtFixedRate(newRunnable(){@Overridepublicvoidrun(){System.out.println("ServiceScheduledExecutor)";}},1,sleepTime,TimeUnit.SECONDS);}4.Quartz的集成Quartz是一个完全用Java编写的开源作业调度框架,它为Java应用程序中的作业调度提供了一种简单但功能强大的机制。要理解它要使用它,你需要了解它的几个核心概念:1)Job:表示一个作业和要执行的具体内容。该接口只有一个方法,如下:voidexecute(JobExecutionContextcontext)2)JobDetail:表示一个具体的可执行调度器,Job是可执行调度器要执行的内容,JobDetail还包括任务调度方案和策略。3)Trigger:表示配置一个调度参数,什么时候调整。4)Scheduler:表示一个调度容器,一个调度容器中可以注册多个JobDetails和Triggers。当Trigger与JobDetail结合时,可以通过Scheduler容器进行调度。有了这些概念,我们就可以将Quartz集成到我们的springboot项目中了。1.引入quartz依赖org.springframework.bootspring-boot-starter-quartz2.配置@ConfigurationpublicclassQuartzConfig{@BeanpublicJobDetailquartzDetail(){returnJobBuilder.newJob(QuartzTest.class).withIdentity("QuartzTest").storeDurably().build();}@BeanpublicSimpleTriggerquartzTrigger(){SimpleScheduleBuilderscheduleBuilder=SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).TriggerForever();returnTriggerBuilder(.).forJob(quartzDetail())。");}}5.使用Scheduled注解@Scheduled是spring为定时任务创建的注解,查看注解源码:@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Repeatable(Schedules.class)public@interfaceScheduled{//cronexpressionStringcron()default"";//接收一个java.util.TimeZone#IDStringzone()default"";//最后执行的时间点有多长afterthatexecutelongfixedDelay()default-1;//支持placeholderstringtypefixedDelayStringfixedDelayString()default"";//距离最后一个执行时间点多久后才执行longfixedRate()default-1;//FixedRateStringStringfixedRateString()default""支持占位符字符串TypeinitialDelayStringinitialDelayString()default"";}可以看出Scheduled注解中的参数是用来设置“定时”动作的。通常,比较常用的参数是cron(),这意味着我们需要学习一些cron表达式的相关语法,但由于内容较多,篇幅较长,这里暂时不做说明。我们会把cron语法放到文末,在这里讲解如何使用Scheduled注解实现定时任务。1)启用定时任务支持@SpringBootApplication/***启用定时任务支持*/@EnableSchedulingpublicclassTestApplicationextendsSpringBootServletInitializer{publicstaticvoidmain(String[]args){SpringApplication.run(TestApplication.class,args);}@OverrideprotectedSpringApplicationBuilderconfigure(SpringApplicationBuilderbuilder){returnsourcebuilder(this.getClass());}}2)使用@ComponentpublicclassScheduledTest{privateLoggerlogger=LoggerFactory.getLogger(ScheduledTest.class);/***每15秒执行一次定时任务*/@Scheduled(cron="0/15****?")publicvoidtestCron(){logger.info("定时执行定时任务");}}6.cron表达式cron表达式是一个字符串,语法为:[second][minute][hour][Day][Month][Week][Year]其中,[Year]是可选的,所以cron表达式通常由6或7部分组成,内容的值是一个数字或者cron表达式的一些特殊约定的字符,这些特殊字符称为“通配符”,每个通配符代表一个值。一个cron表达式可以这样表示:SequentialvaluerangeSpecialstringrangeSecond0~60,-*/minute0~60,-*/hour0-23,-*/day1-31,-*/month1-12/1-12月,-*?/LW第1-7周/SUN-SAT,-*?/L#年份(可省略)1970-2099,-*/通配符的解释及作用如下:通配符所代表的值的解释*所有值如:小时字段为*,表示每小时触发?不指定值如:week字段为?,表示表达式不关心星期几-interval如:hour字段设置为2-5,表示触发在2点、3点、4点、5点,以及多个值如:时间字段设置2、3、5,代表2点、3点、5点它将触发/递增值,如:在小时字段中设置0/2,表示每两小时触发一次,在小时字段中设置2/5,表示从2点开始每5小时触发一次。L最终值,如:在day字段中设置L,表示该月的最后一天W最近的工作日例如:在day字段中设置13W,表示在最近的工作日13日触发一次#序号例如:在week字段中设置5#2,表示每个月的第二个星期五例子:每2秒执行一次:0/5?每5分钟执行一次:00/5*?在1分钟、12分钟、45分钟执行一次:01、12、45*?每天23:59:59执行一次:595923?每月15号凌晨3点执行一次:00315*?每月最后一天12:00执行一次:0012L*?