Spring提供的三种定时任务机制及其比较
spring定时任务详解(@Scheduled注解)
spring定时任务详解(@Scheduled注解)Spring配置⽂件xmlns加⼊xmlns:task="/schema/task"xsi:schemaLocation中加⼊/schema/task/schema/task/spring-task-3.0.xsd"Spring扫描注解的配置<context:component-scan base-package="com.imwoniu.*" />任务扫描注解<task:executor id="executor" pool-size="5" /><task:scheduler id="scheduler" pool-size="10" /><task:annotation-driven executor="executor" scheduler="scheduler" />代码实现:注解@Scheduled 可以作为⼀个触发源添加到⼀个⽅法中,例如,以下的⽅法将以⼀个固定延迟时间5秒钟调⽤⼀次执⾏,这个周期是以上⼀个调⽤任务的完成时间为基准,在上⼀个任务完成之后,5s后再次执⾏:@Scheduled(fixedDelay = 5000)public void doSomething() {// something that should execute periodically}如果需要以固定速率执⾏,只要将注解中指定的属性名称改成fixedRate即可,以下⽅法将以⼀个固定速率5s来调⽤⼀次执⾏,这个周期是以上⼀个任务开始时间为基准,从上⼀任务开始执⾏后5s再次调⽤:@Scheduled(fixedRate = 5000)public void doSomething() {// something that should execute periodically}如果简单的定期调度不能满⾜,那么cron表达式提供了可能package com.imwoniu.task;import org.springframework.scheduling.annotation.Scheduled;import ponent;@Componentpublic class TaskDemo {@Scheduled(cron = "0 0 2 * * ?") //每天凌晨两点执⾏void doSomethingWith(){("定时任务开始......");long begin = System.currentTimeMillis();//执⾏数据库操作了哦...long end = System.currentTimeMillis();("定时任务结束,共耗时:[" + (end-begin) / 1000 + "]秒");}}关于Cron表达式(转载)表达式⽹站⽣成:按顺序依次为秒(0~59)分钟(0~59)⼩时(0~23)天(⽉)(0~31,但是你需要考虑你⽉的天数)⽉(0~11)天(星期)(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)7.年份(1970-2099)其中每个元素可以是⼀个值(如6),⼀个连续区间(9-12),⼀个间隔时间(8-18/4)(/表⽰每隔4⼩时),⼀个列表(1,3,5),通配符。
SpringBoot之旅--定时任务两种(SpringSchedule与Quartz整合)实现
SpringBoot之旅--定时任务两种(SpringSchedule与Quartz整合)实现相关⽂章前⾔最近在项⽬中使⽤到定时任务,之前⼀直都是使⽤Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Schedule 可以帮助我们实现简单的定时任务功能。
下⾯说⼀下两种⽅式在Spring Boot 项⽬中的使⽤。
Spring Schedule 实现定时任务Spring Schedule 实现定时任务有两种⽅式 1. 使⽤XML配置定时任务, 2. 使⽤ @Scheduled 注解。
因为是Spring Boot 项⽬可能尽量避免使⽤XML配置的形式,主要说注解的形式.Spring Schedule 提供三种形式的定时任务:固定等待时间 @Scheduled(fixedDelay = 时间间隔 )@Componentpublic class ScheduleJobs {public final static long SECOND = 1 * 1000;FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");@Scheduled(fixedDelay = SECOND * 2)public void fixedDelayJob() throws InterruptedException {TimeUnit.SECONDS.sleep(2);System.out.println("[FixedDelayJob Execute]"+fdf.format(new Date()));}}固定间隔时间 @Scheduled(fixedRate = 时间间隔 )@Componentpublic class ScheduleJobs {public final static long SECOND = 1 * 1000;FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");@Scheduled(fixedRate = SECOND * 4)public void fixedRateJob() {System.out.println("[FixedRateJob Execute]"+fdf.format(new Date()));}}Corn表达式 @Scheduled(cron = Corn表达式)@Componentpublic class ScheduleJobs {public final static long SECOND = 1 * 1000;FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");@Scheduled(cron = "0/4 * * * * ?")public void cronJob() {System.out.println("[CronJob Execute]"+fdf.format(new Date()));}}Spring Boot 整合 Quartz 实现定时任务添加Maven依赖<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency>Spring Boot 整合 QuartzSpring 项⽬整合 Quartz 主要依靠添加 SchedulerFactoryBean 这个 FactoryBean ,所以在maven 依赖中添加 spring-context-support 。
spring的@Scheduled定时任务,同一时间段的定时任务只会执行一个,其余的会被阻。。。
spring的@Scheduled定时任务,同⼀时间段的定时任务只会执⾏⼀个,其余的会被阻。
现有两个定时任务@Component("aa")public class aa {@Scheduled(cron = "0 44 17 * * ?")public void bb() {try {System.out.println("aa执⾏时间:" + new Date());Thread.sleep(65000);System.out.println("aa完成时间:" + new Date());} catch (Exception e) {e.printStackTrace();}}}@Component("bb")public class bb {@Scheduled(cron = "0 55 17 * * ?")public void aa() {try {System.out.println("bb执⾏时间:" + new Date());Thread.sleep(10000);System.out.println("bb完成时间:" + new Date());} catch (Exception e) {e.printStackTrace();}}}默认的在启动项加⼊@EnableScheduling注解就可以运⾏了最终,执⾏的结果令⼈⼤跌眼镜。
aa的任务由于执⾏时间需要65秒,超过了bb任务执⾏的时间,结果bb任务执⾏的时间被阻塞掉,延迟了5秒执⾏。
解决⽅法是在启动项类中加⼊如下配置即可@Beanpublic TaskScheduler taskScheduler() {ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();taskScheduler.setPoolSize(50);return taskScheduler;}如果是xml<!-- 注解式 --><task:annotation-driven executor="myExecutor" scheduler="myScheduler"/><task:executor id="myExecutor" pool-size="5"/><task:scheduler id="myScheduler" pool-size="10"/>。
spring定时任务配置
定时任务解决方案两种方案,基本上都是一样,就是配置时间规则的时候,不一致。
两种方案:CronTrigger基于日历和时间,SimpleTrigger基于时间。
方案一是CronTrigger 配置,方案二是SimpleTrigger配置。
Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。
Quartz 允许开发人员根据时间间隔(或天)来调度作业。
它实现了作业和触发器的多对多关系,还能把多个作业与不同的触发器关联。
整合了 Quartz 的应用程序可以重用来自不同事件的作业,还可以为一个事件组合多个作业。
SimpleTrigger当需要在规定的时间执行一次或在规定的时间段以一定的时间间隔重复触发执行Job时,SimpleTrigger就可以满足要求;SimpleTrigger的属性有:开始时间、结束时间、重复次数和重复的时间间隔,重复次数属性的值可以为0、正整数、或常量 SimpleTrigger.REPEAT_INDEFINITELY,重复的时间间隔属性值必须为0或长整型的正整数,以毫秒作为时间单位,当重复的时间间隔为0时,意味着与Trigger 同时触发执行(或几乎与Scheduler开始时同时触发执行)。
如果有指定结束时间属性值,则结束时间属性优先于重复次数属性,这样的好处在于:当我们需要创建一个每间隔10秒钟触发一次直到指定的结束时间的 Trigger,而无需去计算从开始到结束的所重复的次数,我们只需简单的指定结束时间和使用REPEAT_INDEFINITELY作为重复次数的属性值即可(我们也可以指定一个比在指定结束时间到达时实际执行次数大的重复次数)。
方案一先写一个业务类,然后进行如下配置,一步都不能少,这样就能完成一个定时任务。
第一步写一个业务类这个业务很简单,不需要实现任务spring的接口。
就是一个普通业务类,然后写一个业务方法。
到时候配置定时任务,就会定时的执行这个业务方法。
JAVA:定时器的三种方法(详细注解)
JAVA:定时器的三种⽅法(详细注解)在Java中为我们提供了Timer来实现定时任务,当然现在还有很多定时任务框架,⽐如说Spring、QuartZ、Linux Cron等等,⽽且性能也更加优越。
但是我们想要深⼊的学习就必须先从最简单的开始。
第⼀种:创建⼀个thread,然后让它在while循环⾥⼀直运⾏着,通过sleep⽅法来达到定时任务的效果,代码如下public class Task1 {public static void main(String[] args) {// run in a second// 每⼀秒钟执⾏⼀次final long timeInterval = 1000;Runnable runnable = new Runnable() {public void run() {while (true) {// ------- code for task to run// ------- 要运⾏的任务代码System.out.println("Hello, stranger");// ------- ends heretry {// sleep():同步延迟数据,并且会阻塞线程Thread.sleep(timeInterval);} catch (InterruptedException e) {e.printStackTrace();}}}};//创建定时器Thread thread = new Thread(runnable);//开始执⾏thread.start();}}第⼆种:启动和去取消任务时可以控制,可以指定你想要的delay(开始执⾏的等待时间)时间,在实现时,Timer类可以调度任务,TimerTask 则是通过在run()⽅法⾥实现具体任务。
Timer实例可以调度多任务,它是线程安全的。
当Timer的构造器被调⽤时,它创建了⼀个线程,这个线程可以⽤来调度任务。
java中实现定时任务的常用方式,以及差异和注意事项。
java中实现定时任务的常用方式,以及差异和注意事项。
1 Java中实现定时任务的常用方式在Java中,实现定时任务的方式很多,以下是目前比较常用的几种方式:1.1 Timer和TimerTaskTimer和TimerTask是Java中自带的定时任务实现方式。
Timer 是一个定时器类,支持在指定时间后执行任务,并且支持延迟和定时重复执行任务。
TimerTask则是一个实现了Runnable接口的抽象类,通过继承TimerTask并实现run()方法来定义具体的任务。
1.2 ScheduledExecutorServiceScheduledExecutorService是Java中提供的一种用于执行定时任务的线程池。
与Timer和TimerTask相比,ScheduledExecutorService的在线程安全性、定时任务的精度、定时任务的灵活性等方面有很大的改进。
ScheduledExecutorService支持延迟和定时重复执行任务,并且可以控制定时任务的执行周期、并发性等。
1.3 Spring中的@ScheduledSpring框架中提供了@Scheduled注解来支持定时任务的实现。
通过在指定的方法上加上@Scheduled注解,指定定时任务的执行周期和策略,就可以很方便地实现定时任务。
@Scheduled注解的实现依赖于ScheduledExecutorService。
1.4 Quartz框架Quartz是一个高效、灵活、可靠的开源定时任务调度框架,它提供了大量的功能和扩展点,并且可以与Spring等框架集成使用。
使用Quartz框架可以非常方便地实现复杂的定时任务逻辑,比如任务调度的优先级、任务的依赖关系、任务的失败重试等。
2. 差异与注意事项不同的定时任务实现方式在功能和特性上有差异,因此在选择合适的定时任务实现方式时需要考虑以下几点:2.1 精度和性能不同的定时任务实现方式在任务执行的精度和性能上有差异。
Spring@Scheduled定时任务的fixedRate,fixedDelay,cro。。。
Spring@Scheduled定时任务的fixedRate,fixedDelay,cro。
⼀. 三种定时类型。
1.cron --@Scheduled(cron="0/5 * * * *?")当时间达到设置的时间会触发事件。
上⾯那个例⼦会每5秒执⾏⼀次。
2018/1/4 14:27:302018/1/4 14:27:352018/1/4 14:27:402018/1/4 14:27:452018/1/4 14:27:502.fixedRate --@Scheduled(fixedRate=2000)每两秒执⾏⼀次时间。
3.fixedDelay --@Scheduled(fixedDelay=2000)每次任务执⾏完之后的2s后继续执⾏看字⾯意思容易理解,但是任务执⾏长度超过周期会怎样呢?不多说,直接上图:import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import org.springframework.scheduling.annotation.Scheduled;import ponent;@Componentpublic class MyProcessor{DateFormat sdf = new SimpleDateFormat("HH:mm:ss");int[] delays = new int[]{8,3,6,2,2};int index = 0;@Scheduled(cron = "0/5 * * * * ?}")public void process() {try {if(index > delays.length - 1){if(index == delays.length){System.out.println("---------- test end at " + sdf.format(new Date()) + " ---------");}index ++;return;}else{System.out.println(index + ":start run at" + sdf.format(new Date()));}Thread.sleep(delays[index] * 1000);System.out.println(index + ":end run at " + sdf.format(new Date()));index ++;} catch (InterruptedException e) {e.printStackTrace();}}}。
Spring@EnableScheduling定时任务用法总结
Spring@EnableScheduling定时任务用法总结1. 原理1.1 TaskSchedulerTaskScheduler是spring的定时任务使用的线程池的关键类public interface TaskScheduler {// 通过Trigger执行任务ScheduledFuture schedule(Runnable task, Trigger trigger);// 指定时间执行任务ScheduledFuture schedule(Runnable task, Date startTime);// 指定在指定时间后,循环周期执行任务ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);// 循环周期执行任务ScheduledFuture scheduleAtFixedRate(Runnable task, long period);// 延迟N时间,在指定日期执行ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);}•1•2•3•4•5•6•7•8•9•10•11•12•13•14•1•2•3•4•5•6•7•8•9•10•11•12•13•14TaskScheduler有两种实现方式:- TimerManagerTaskScheduler:使用外部对象管理线程池,如CommonJ TimerManager,适用于多个进程共享线程池- ThreadPoolTaskScheduler:如果仅仅在同一进程管理线程池,则推荐使用此对象。
Spring中的定时调度(Scheduling)和线程池(ThreadPooling)
23.1. 简介Spring包含了对定时调度服务的内置支持类。
当前,Spring支持从JDK1.3开始内置的Timer类和Quartz Scheduler(/)。
二者都可以通过FactoryBean,分别指向Timer或Trigger实例的引用进行配置。
更进一步,有个对Quartz Scheduler和Timer都有效的工具类可以让你调用某个目标对象的方法(类似通常的MethodInvokingFactoryBean操作)。
Spring 还包含有用于线程池调度的类,它针对Java 1.3,1.4,5和JEE环境的差异都进行了抽象。
23.2. 使用OpenSymphony Quartz 调度器Quartz使用Trigger, Job以及JobDetail等对象来进行各种类型的任务调度。
关于Quartz的基本概念,请参阅。
为了让基于Spring的应用程序方便使用,Spring提供了一些类来简化uartz的用法。
使用JobDetailBeanJobDetail对象保存运行一个任务所需的全部信息。
Spring提供一个叫作JobDetailBean的类让JobDetail能对一些有意义的初始值进行初始化。
让我们来看个例子:<bean name="exampleJob" class=""><property name="jobClass" value="example.ExampleJob" /><property name="jobDataAsMap"><map><entry key="timeout" value="5" /></map></property></bean>Job detail bean拥有所有运行job(ExampleJob)的必要信息。
SpringBoot三种定时任务实现方式
SpringBoot三种定时任务实现方式在Spring Boot项目中,实现定时任务是常见需求。
Spring Boot提供了多种灵活的方式来实现定时任务,包括基于注解的方式、基于接口的方式以及使用外部任务调度工具等。
定时任务作为一种系统调度工具,在一些需要有定时作业的系统中应用广泛,如每逢某个时间点统计数据、在将来某个时刻执行某些动作...定时任务在主流开发语言均提供相应的API供开发者调用,在Java中,实现定时任务有很多种方式,原生的方式实现一个完整定时任务需要由Timer、TimerTask两个类,Timer 是定时器类,用来按计划开启后台线程执行指定任务,TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务。
除此之外,还可以用ScheduledExecutorService类或者使用第三方jar库Quartz,其中Quartz是一个优秀的定时任务框架,发展至今已经非常成熟,以致后来其他的定时任务框架的核心思想或底层大多源于Quartz。
springboot作为Java的一种开发框架,在springboot项目中实现定时任务不仅可以使用Java提供的原生方式,还可以使用springboot提供的定时任务API。
本文将详细介绍三种常用的Spring Boot定时任务实现方式,并提供相应的例子代码。
1. 基于注解的方式(@Scheduled)使用@Scheduled注解是实现Spring Boot定时任务最简单直接的方式。
首先,你需要在Spring Boot的启动类或者配置类上添加@EnableScheduling注解来启用定时任务支持。
然后,在需要定时执行的方法上添加@Scheduled注解,并指定cron表达式或固定间隔。
例子代码:在上面的代码中,@Scheduled注解分别使用了cron表达式和固定频率(fixedRate)两种方式来定义定时任务。
需要注意的是,@EnableScheduling 注解只需要在Spring Boot的启动类或配置类上添加一次。
spring定时任务
Chapter 23. Spring中的定时调度(Scheduling)和线程池(Thread Pooling)23.1. 简介Spring包含了对定时调度服务的内置支持类。
当前,Spring支持从JDK1.3开始内置的Timer类和QuartzScheduler(/quartz/)。
二者都可以通过FactoryBean,分别指向Timer或Trigger实例的引用进行配置。
更进一步,有个对Quartz Scheduler和Timer都有效的工具类可以让你调用某个目标对象的方法(类似通常的MethodInvokingFactoryBean操作)。
Spring 还包含有用于线程池调度的类,它针对Java 1.3,1.4,5和JEE环境的差异都进行了抽象。
23.2. 使用OpenSymphony Quartz 调度器Quartz使用Trigger, Job以及JobDetail等对象来进行各种类型的任务调度。
关于Quartz的基本概念,请参阅/quartz。
为了让基于Spring的应用程序方便使用,Spring提供了一些类来简化uartz的用法。
23.2.1. 使用JobDetailBeanJobDetail对象保存运行一个任务所需的全部信息。
Spring提供一个叫作JobDetailBean的类让JobDetail能对一些有意义的初始值进行初始化。
让我们来看个例子:<bean name="exampleJob"class="org.springframework.scheduling.quartz.JobDetailBean"><property name="jobClass" value="example.ExampleJob" /><property name="jobDataAsMap"><map><entry key="timeout" value="5" /></map></property></bean>Job detail bean拥有所有运行job(ExampleJob)的必要信息。
SpringBoot中定时任务的3种实现方式
SpringBoot中定时任务的3种实现⽅式Ref定时任务的实现⽅式⽅式1:基于java.util.Timer定时器,实现类似闹钟的定时任务⽅式2:使⽤ Quartz、elastic-job、xxl-job 等开源第三⽅定时任务框架,适合分布式项⽬应⽤。
该⽅式的缺点是配置复杂。
⽅式3:使⽤ Spring 提供的⼀个注解@Schedule,开发简单,使⽤⽐较⽅便。
java.util.Timer实现定时任务基于java.util.Timer定时器,实现类似闹钟的定时任务。
这种⽅式在项⽬中使⽤较少,参考如下Demo。
import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class SpringbootAppApplication {/*** main⽅法* @param args*/public static void main(String[] args) {SpringApplication.run(SpringbootAppApplication.class, args);System.out.println("Server is running ...");TimerTask timerTask = new TimerTask() {@Overridepublic void run() {System.out.println("task run:"+ new Date());}};Timer timer = new Timer();timer.schedule(timerTask,10,3000);}}复制代码ScheduledExecutorService实现定时任务该⽅法类似Timer,参考如下Demo。
public class TestScheduledExecutorService {public static void main(String[] args) {ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();/*** @param command the task to execute 任务体* @param initialDelay the time to delay first execution ⾸次执⾏的延时时间* @param period the period between successive executions 任务执⾏间隔* @param unit the time unit of the initialDelay and period parameters 间隔时间单位*/service.scheduleAtFixedRate(()->System.out.println("task ScheduledExecutorService "+new Date()), 0, 3, TimeUnit.SECONDS);service.scheduleAtFixedRate(()->System.out.println("task ScheduledExecutorService "+new Date()), 0, 3, TimeUnit.SECONDS);}}复制代码@Schedule实现定时任务Demo1. ⾸先,在项⽬启动类上添加@EnableScheduling注解,开启对定时任务的⽀持。
定时任务任务的三种方法
定时任务任务的三种⽅法1,spring整合quartz⽅式,这种⽹上资料太多,简单引⽤⼀下就ok。
<bean id="taskJob" class="com.tyyd.dw.task.DataConversionTask"/><bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="group" value="job_work"/><property name="name" value="job_work_name"/><!--false表⽰等上⼀个任务执⾏完后再开启新的任务--><property name="concurrent" value="false"/><property name="targetObject"><ref bean="taskJob"/></property><property name="targetMethod"><value>run</value></property></bean><!-- 调度触发器 --><bean id="myTrigger"class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"><property name="name" value="work_default_name"/><property name="group" value="work_default"/><property name="jobDetail"><ref bean="jobDetail"/></property><property name="cronExpression"><value>0/5 * * * * ?</value></property></bean><!-- 调度⼯⼚ --><bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="triggers"><list><ref bean="myTrigger"/></list></property></bean>2.spring task⽅式的定时任务(最为简单,功能也简单)<!-- 定时器配置开始--><bean id="task1" class="com.XXX.Task1"></bean><bean id="task2" class="com.XXX.Task2"></bean><task:scheduled-tasks><task:scheduled ref="task1" method="execute" cron="0 */1 * * * ?"/><task:scheduled ref="task2" method="execute" cron="0 */1 * * * ?"/></task:scheduled-tasks><!-- 定时器配置结束-->使⽤的时候,直接写⼀个类,⼀个⽅法就可以了,简单快捷。
SpringBoot定时任务动态修改cron表达式改变执行周期
SpringBoot定时任务动态修改cron表达式改变执⾏周期⼀、场景引⼊前不久做过⼀个根据下载指令定时下载⽂件到服务器的需求。
轮询下载的周期需要根据下载任务量的⼤⼩动态修改,下载任务密集的时候就周期缩⼩,下载任务少量时就扩⼤周期时间。
java本⾝和第三⽅开源框架Spring共有三种执⾏定时任务的⽅式:1) Java⾃带的java.util.Timer类:这个类允许你调度⼀个java.util.TimerTask任务。
(这种⽅式⽐较古⽼,⾃从第三⽅开源框架出现以来,基本不使⽤java⾃带的定时任务组件)2) 开源的第三⽅框架: Quartz 或者 elastic-job ,但是这个⽐较复杂和重量级,适⽤于分布式场景下的定时任务,可以根据需要多实例部署定时任务。
3) 使⽤Spring提供的注解: @Schedule 。
如果定时任务执⾏时间较短,并且⽐较单⼀,可以使⽤这个注解。
以上三种执⾏定时任务的⽅式都只能固定执⾏周期,⼀旦定时任务跑起来之后就不可能修改周期,只能修改周期后重新启动,现在需要动态修改执⾏周期,故这三种⽅式都不能使⽤。
⼆、解决⽅式既然不能⽤通过传统的⽅式,那就要想到强⼤的第三⽅开源框架带来的便利,Spring从3.0版本开始在框架中加⼊了⼀个新的定时任务线程池配置类,即:org.springframework.scheduling.concurrent包中有⼀个ThreadPoolTaskScheduler类,它继承了抽象类ExecutorConfigurationSupport并实现了AsyncListenableTaskExecutor,SchedulingTaskExecutor,TaskScheduler三个接⼝,其中实现了TaskScheduler中的⼀个⽅法:ScheduledFuture<?> schedule(Runnable task, Trigger trigger)源码:@Overridepublic ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {ScheduledExecutorService executor = getScheduledExecutor();try {ErrorHandler errorHandler =(this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule();}catch (RejectedExecutionException ex) {throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);}}通过源码即可发现只要将对应的定时任务的线程以及包含cron表达式的 Trigger 参数传⼊即可按指定的周期启动定时任务。
SpringBoot中并发定时任务的实现、动态定时任务的实现(看这一篇就够了)
SpringBoot中并发定时任务的实现、动态定时任务的实现(看这⼀篇就够了)原创不易,如需转载,请注明出处,否则将追究法律责任!!!⼀、在JAVA开发领域,⽬前可以通过以下⼏种⽅式进⾏定时任务1、单机部署模式Timer:jdk中⾃带的⼀个定时调度类,可以简单的实现按某⼀频度进⾏任务执⾏。
提供的功能⽐较单⼀,⽆法实现复杂的调度任务。
ScheduledExecutorService:也是jdk⾃带的⼀个基于线程池设计的定时任务类。
其每个调度任务都会分配到线程池中的⼀个线程执⾏,所以其任务是并发执⾏的,互不影响。
Spring Task:Spring提供的⼀个任务调度⼯具,⽀持注解和配置⽂件形式,⽀持Cron表达式,使⽤简单但功能强⼤。
Quartz:⼀款功能强⼤的任务调度器,可以实现较为复杂的调度功能,如每⽉⼀号执⾏、每天凌晨执⾏、每周五执⾏等等,还⽀持分布式调度,就是配置稍显复杂。
2、分布式集群模式(不多介绍,简单提⼀下)问题:I、如何解决定时任务的多次执⾏?II、如何解决任务的单点问题,实现任务的故障转移?问题I的简单思考:1、固定执⾏定时任务的机器(可以有效避免多次执⾏的情况,缺点就是单点故障问题)。
2、借助Redis的过期机制和分布式锁。
3、借助mysql的锁机制等。
成熟的解决⽅案:1、Quartz:可以去看看这篇⽂章[Quartz分布式]( https:///jiafuwei/p/6145280.html)。
2、elastic-job:(https:///elasticjob/elastic-job-lite)当当开发的弹性分布式任务调度系统,采⽤zookeeper实现分布式协调,实现任务⾼可⽤以及分⽚。
3、xxl-job:(https:///xuxueli/xxl-job)是⼤众点评员发布的分布式任务调度平台,是⼀个轻量级分布式任务调度框架。
4、saturn:(https:///vipshop/Saturn) 是唯品会提供⼀个分布式、容错和⾼可⽤的作业调度服务框架。
spring定时任务原理
spring定时任务原理参考⽂章: https://juejin.im/post/5b64448af265da0f7f44c201https://juejin.im/post/5e338ebae51d4558864b1ca01、开发中使⽤时要注意的点 (0)spring定时任务执⾏原理实际使⽤的是JDK⾃带的ScheduledExecutorService (1)spring默认使⽤单线程的线程池去执⾏定时任务,所以如果某个任务执⾏时间过长,会导致其他定时任务阻塞⽆法执⾏。
(2)可以开启并⾏调度,springboot中的使⽤⽅式:这种模式每次任务执⾏都会创建⼀个线程去执⾏。
@EnableAsync@EnableScheduling@SpringBootApplicationpublic class QuickMediaApplication {public static void main(String[] args) {SpringApplication.run(QuickMediaApplication.class, args);}@Scheduled(cron = "0/1 * * * * ?")@Asyncpublic void sc1() {System.out.println(Thread.currentThread().getName() + " | sc1 " + System.currentTimeMillis());}} 风险:如果某个定时任务出现死循环或者执⾏时间过长⽽出发时间较短,会导致线程数量不可控。
(3)最稳妥的处理⽅式:⾃定义任务执⾏的线程池,如下: 普通spring配置:@Beanpublic AsyncTaskExecutor asyncTaskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setThreadNamePrefix("task-schedule-");executor.setMaxPoolSize(10);executor.setCorePoolSize(3);executor.setQueueCapacity(0);executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());return executor;}或@Beanpublic ScheduleExecutorService scheduleExecutorService{return Executors.new ScheduleThreadPool(10);} springboot中配置:spring.task.scheduling.pool.size=10spring.task.scheduling.thread-name-prefix=task-schedule-2、源码分析 通过监听IOC容器初始化事件,扫描所有Bean中带有@Scheduled注解的⽅法,然后封装成Task⼦类放置到ScheduledTaskRegistrar中。
java中Springtask定时任务的深入理解
java中Springtask定时任务的深⼊理解java 中Spring task定时任务的深⼊理解在⼯作中有⽤到spring task作为定时任务的处理,spring通过接⼝TaskExecutor和TaskScheduler这两个接⼝的⽅式为异步定时任务提供了⼀种抽象。
这就意味着spring容许你使⽤其他的定时任务框架,当然spring⾃⾝也提供了⼀种定时任务的实现:spring task。
spring task⽀持线程池,可以⾼效处理许多不同的定时任务。
同时,spring还⽀持使⽤Java⾃带的Timer定时器和Quartz定时框架。
限于篇幅,这⾥将只介绍spring task的使⽤。
其实,官⽅⽂档已经介绍地⾜够详细,只不过都是英⽂版,所以为了更好地理解并使⽤spring task,⾸先会对spring task的实现原理做⼀个简单的介绍,然后通过实际代码演⽰spring task是如何使⽤的。
这⾥会涉及到⼀个很重要的知识点:cron表达式。
TaskExecutor和TaskSchedulerTaskExecutor是spring task的第⼀个抽象,它很⾃然让⼈联想到jdk中concurrent包下的Executor,实际上TaskExecutor就是为区别于Executor才引⼊的,⽽引⼊TaskExecutor的⽬的就是为定时任务的执⾏提供线程池的⽀持,那么,问题来了,为什么spring不直接使⽤jdk⾃带的Executor呢?TaskExecutor源码如下?public interface TaskExecutor extends Executor {void execute(Runnable var1);}那么,答案很显然,TaskExecutor提供的线程池⽀持也是基于jdk⾃带的Executor的。
⽤法于Executor没有什么不同。
TaskScheduler是spring task的第⼆个抽象,那么从字⾯的意义看,TaskScheduler就是为了提供定时任务的⽀持咯。
spring中定时任务管理
spring定时任务管理1.使用方式1.在方法上使用定时任务注解为@Scheduled(*)2.Xml配置方式<task:scheduled ref="taskJob" method="job1" cron="0 05 * * ?"/> </task:scheduled-tasks>3.实现SchedulingConfigurer接口,并持有ScheduledTaskRegistrar进行动态注册任务2.支持设置的调度规则内部可以设置的调度规则有cron zone fixedDelay fixedDelayString fixedRateinitialDelay initialDelayStringi.cron表达式语法(注:[年]不是必须的域,可以省略[年],则一共6个域)[秒] [分] [小时] [日] [月] [周] [年]每隔5秒执行一次:*/5 * * * * ?每隔1分钟执行一次:0 */1 * * * ?每天23点执行一次:0 0 23 * * ?每天凌晨1点执行一次:0 0 1 * * ?每月1号凌晨1点执行一次:0 0 1 1 * ?每月最后一天23点执行一次:0 0 23 L * ?每周星期六凌晨1点实行一次:0 0 1 ? * L在26分、29分、33分执行一次:0 26,29,33 * * * ?每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?cron表达式使用占位符cron属性接收的cron表达式支持占位符。
"${time.cron}"•* 表示所有值。
例如:在分的字段上设置*,表示每一分钟都会触发。
•? 表示不指定值。
使用的场景为不需要关心当前设置这个字段的值。
例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为”?” 具体设置为0 0 0 10 * ?•- 表示区间。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Spring提供的三种定时任务机制及其比较定时任务的需求在众多应用系统中广泛存在,在Spring中,我们可以使用三种不同的定时机制,下面一一描述并加以比较1. 基于Quartz的定时机制下面详细解释这个类图中涉及的关键类及其使用场景1.1. SchedulerFactoryBean这是Spring中基于Quartz的定时机制入口,只要Spring容器装载了这个类,Quartz定时机制就会启动,并加载定义在这个类中的所有triggerSpring配置范例:[xhtml]view plaincopy1.<bean id="sfb"class="org.springframework.scheduling.quartz.SchedulerFactoryBean">2.<!-- 添加触发器 -->3.<property name="triggers">4.<list>5.<ref local="appSubscTrigger"/>6.</list>7.</property>8.9.<!-- 添加listener -->10.<property name="globalTriggerListeners">11.<list>12.<ref local="myTaskTriggerListener"/>13.</list>14.</property>15.</bean>1.2. CronTriggerBean实现了Trigger接口,基于Cron表达式的触发器这种触发器的好处是表达式与linux下的crontab一致,能够满足非常复杂的定时需求,也容易配置Spring配置范例:[xhtml]view plaincopy1.<bean id="notifyTrigger"class="org.springframework.scheduling.quartz.CronTriggerBean">2.<property name="jobDetail"ref="notifyJobDetail"/>3.<property name="cronExpression"value="${notify_trigger_cron_expression}"/>4.</bean>1.3. SimpleTriggerBean该类也实现了Trigger接口,基于配置的定时调度这个触发器的优点在于很容易配置一个简单的定时调度策略Spring配置范例:[xhtml]view plaincopy1.<bean id="simpleReportTrigger"class="org.springframework.scheduling.quartz.SimpleTriggerBean">2.<property name="jobDetail">3.<ref bean="reportJob"/>4.</property>5.<property name="startDelay">6.<value>3600000</value>7.</property>8.<property name="repeatInterval">9.<value>86400000</value>10.</property>11.</bean>1.4. JobDetailBeanJobDetail类的简单扩展,能够包装一个继承自QuartzJobBean的普通Bean,使之成为定时运行的Job缺点是包装的Bean必须继承自一个指定的类,通用性不强,对普通Job的侵入性过强,不推荐使用1.5. MethodInvokingJobDetailFactoryBeanSpring提供的一个不错的JobDetail包装工具,能够包装任何bean,并执行类中指定的任何stati或非static的方法,避免强制要求bean去实现某接口或继承某基础类Spring配置范例:[xhtml]view plaincopy1.<bean id="notifyJobDetail"parent="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">2.<property name="targetObject"ref="notifyServerHandler"/>3.<property name="targetMethod"value="execute"/>4.</bean>1.6. 关于TriggerListener和JobListenerQuartz中提供了类似WebWork的拦截器的功能,系统执行任务前或任务执行完毕后,都会检查是否有对应的Listener需要被执行,这种AOP的思想为我们带来了灵活的业务需求实现方式。
例如现在有一个简单的业务要求:任务执行前先判断当前服务器是否为task服务器,不是则不执行任务。
对于这种业务需求,我们可以简单的实现一个TriggerListener,并将其插入SchedulerFactoryBean的globalTriggerListeners中,这样所有的job在执行前后都会调用TriggerListener中对应的方法。
代码范例:[java]view plaincopy1.public class MyTaskTriggerListener implements TriggerListener {2.protected static final Log logger = LogFactory.getLog(MyTaskTriggerListener.class);3.4./**5. * 需要运行task任务的机器列表6. */7.private String taskServers;8.9.public String getName() {10.return"MyTaskTriggerListener";11. }12.13.public void triggerComplete(Trigger arg0, JobExecutionContext arg1, intarg2) {14. }15.16.public void triggerFired(Trigger arg0, JobExecutionContext arg1) {17. }18.19.public void triggerMisfired(Trigger arg0) {20. }21.22./**23. * 判断当前服务器是否为task服务器,来决定是否执行task24. * @return25. */26.public boolean vetoJobExecution(Trigger arg0, JobExecutionContext arg1){27. String serverName;28.try {29. serverName = InetAddress.getLocalHost().getHostName();//获取主机名30. } catch (UnknownHostException e) {31. e.printStackTrace();32.return true;33. }34.if (taskServers.indexOf(serverName) > -1) {35.if (logger.isInfoEnabled()) {36. ("this is a task server, job will be executed");37. }38.return false;39. } else {40.if (logger.isInfoEnabled()) {41. ("this is not a task server, job will be vetoed");42. }43.return true;44. }45. }46.47.public String getTaskServers() {48.return taskServers;49. }50.51.public void setTaskServers(String taskServers) {52.this.taskServers = taskServers;53. }54.}2. 基于Timer的定时机制JDK提供了基础的定时类:Timer,在这个类的基础上,Spring提供了一套简单的定时机制下面详细解释这个类图中涉及的关键类及其使用场景2.1. TimerFactoryBean这个类非常类似Quartz中的SchedulerFactoryBean,是基于Timer的定时机制的入口,Spring容器装载此类后会自动开始定时器Spring配置范例:[xhtml]view plaincopy1.<bean id="timerFactory"class="org.springframework.scheduling.timer.TimerFactoryBean">2.<property name="scheduledTimerTasks">3.<list>4.<ref bean="scheduledTask"/>5.</list>6.</property>7.</bean>2.2. ScheduledTimerTask类似于Quartz中的Trigger的SimpleTriggerBean实现,任务是在设定的时间触发并执行配置的任务,特点是配置简单、明了,使用于简单的任务触发逻辑Spring配置范例:[xhtml]view plaincopy1.<bean id=”scheduledReportTask”class=”org.springframework.scheduling.timer.ScheduledTimerTask”>2.<property name=”timerTask”>3.<ref bean=”reportTimerTask”/>4.</property>5.<property name=”period”>6.<value>86400000</value>7.</property>8.</bean>2.3. TimerTask抽象类普通task实现必须要继承的父类,主要包含一个run()的方法,类似Quartz中的QuartzJobBean,对应用侵入性较强,也不推荐使用2.4. MethodInvokingTimerTaskFactoryBean类似Quartz中的MethodInvokingJobDetailFactoryBean,用于封装任何bean,并可以执行bean中的任意方法,不再复述3. 基于Executor的定时机制这种定时机制与上面两种定时机制没有太大区别,特别是在配置和实现功能上,不同的是它的核心是基于ScheduledExecutorService(ScheduledThreadPoolExecutor是默认实现),一种JDK5.0中提供的基于线程的并发机制,关于JDK5中的线程池的概念及其一些深入分析,请参考老唐的博客:/sfdev/archive/2008/12/30/3648457.aspx这里不再复述4. 三种定时机制的比较和案例分析看完了这三种定时机制,各有各的优劣,不同场景下我们应该灵活选择不同的定时机制。