一、什么是任务调度

任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务,本文会介绍Timer、ScheduledExecutor、Quartz、Spring Boot中的调度模块使用。

二、Timer

Timer任务调度的核心类是 Timer 和 TimerTask。其中Timer负责设定TimerTask的起始与间隔执行时间。使用者只需要创建一个 TimerTask 的继承类,实现自己的run方法,然后将其丢给 Timer 去执行即可。

下面的例子每隔半秒执行run中的方法,输出当前时间和name。

public class Main {public static void main(String[] args) throws ClassNotFoundException {Timer timer = new Timer();timer.schedule(new TestTimerTask("test"), 0, 500);}static class TestTimerTask extends TimerTask {private String name;public TestTimerTask(String name) {this.name = name;}@Overridepublic void run() {System.out.println(LocalDateTime.now()+"-----run----" + name);}}
}

运行结果:

2020-05-19T09:19:11.301-----run----test
2020-05-19T09:19:11.741-----run----test
2020-05-19T09:19:12.241-----run----test
2020-05-19T09:19:12.742-----run----test
2020-05-19T09:19:13.242-----run----test
2020-05-19T09:19:13.742-----run----test
2020-05-19T09:19:14.242-----run----test
2020-05-19T09:19:14.743-----run----test
2020-05-19T09:19:15.243-----run----test
2020-05-19T09:19:15.743-----run----test
2020-05-19T09:19:16.244-----run----test
2020-05-19T09:19:16.743-----run----test
2020-05-19T09:19:17.243-----run----test

因为Timer底层是使用一个单线来实现多个Timer任务处理的,所有任务都是由同一个线程来调度,所有任务都是串行执行,意味着同一时间只能有一个任务得到执行,而某一个任务的延迟或者异常会影响到之后的任务。如下面这段,当test2抛出异常后,test也会终止。

public class Main {public static void main(String[] args) throws ClassNotFoundException {Timer timer = new Timer();timer.schedule(new TestTimerTask("test"), 0, 500);timer.schedule(new TestTimerTask("test2"), 0, 500);}static class TestTimerTask extends TimerTask {private String name;private int count ;public TestTimerTask(String name) {this.name = name;}@Overridepublic void run() {if ("test2".equals(name)){count++;if (count>5){throw  new NullPointerException();}}System.out.println(LocalDateTime.now()+"-----run----" + name);}}
}

三、ScheduledExecutor

鉴于 Timer 的上述缺陷,Java 5 推出了基于线程池设计的 ScheduledExecutor。其设计思想是,每一个被调度的任务都会由线程池中一个线程去执行,因此任务是并发执行的,相互之间不会受到干扰。需要注意的是,只有当任务的执行时间到来时,ScheduedExecutor 才会真正启动一个线程,其余时间 ScheduledExecutor 都是在轮询任务的状态。

下面这段是每隔一秒执行一次任务。

public class Main {public static void main(String[] args) throws ClassNotFoundException {ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);scheduledExecutorService.scheduleWithFixedDelay(new TestRunnable("test1"),0,1, TimeUnit.SECONDS);}static class TestRunnable  implements Runnable{private String name;public TestRunnable(String name) {this.name = name;}@Overridepublic void run() {System.out.println(LocalDateTime.now()+"-----run----" + name);}}
}

运行结果:

2020-05-19T09:30:07.005-----run----test1
2020-05-19T09:30:08.005-----run----test1
2020-05-19T09:30:09.006-----run----test1
2020-05-19T09:30:10.006-----run----test1

ScheduledExecutorService中常用的调度方法是scheduleAtFixedRate和scheduleWithFixedDelay。

scheduleAtFixedRate每次执行时间为上一次任务开始起向后推一个时间间隔,即每次执行时间为 :initialDelay, initialDelay+period, initialDelay+2*period, …。

scheduleWithFixedDelay每次执行时间为上一次任务结束起向后推一个时间间隔,即每次执行时间为:initialDelay, initialDelay+executeTime+delay, initialDelay+2executeTime+2delay。由此可见,scheduleAtFixedRate是基于固定时间间隔进行任务调度,ScheduleWithFixedDelay取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度。

四、Quartz

Quartz是一个由OpenSymphony组织开源的java调度框架。特点如下。

(1)具有强大的调度功能,很容易与spring集成,形成灵活可配置的调度功能。
(2)调度环境的持久化机制:可以保存并恢复调度现场,即使系统因为故障关闭,任务调度现场的数据并不会丢失。
(3)灵活的应用方式:可以灵活的定义触发器调度的时间表,并可以对触发器与任务进行关联映射;
(4)分布式与集群能力。

 <dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version></dependency>

下面这段还是每隔1秒打印当前时间。

public class Main   {public static void main(String[] args) throws SchedulerException {JobDetail jobDetail =JobBuilder.newJob(SimpleQuartzJob.class).withIdentity("testJob","group").build();SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("testTrigger", "group").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()).build();StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();Scheduler scheduler = stdSchedulerFactory.getScheduler();scheduler.start();scheduler.scheduleJob(jobDetail,trigger);}
}public class SimpleQuartzJob implements Job {public SimpleQuartzJob() {}public void execute(JobExecutionContext context) throws JobExecutionException {System.out.println(LocalDateTime.now()+"   "+context.getJobDetail().getKey().getName());}
}

Quartz 设计的核心类包括 Scheduler, Job 以及 Trigger。其中,Job 负责定义需要执行的任务,Trigger 负责设置调度策略,Scheduler 将二者组装在一起,并触发任务开始执行。

另外Quartz也支持cron表达式,如下,*/1 * * * * ?为每隔1秒执行一次。

public class Main   {public static void main(String[] args) throws SchedulerException {JobDetail jobDetail =JobBuilder.newJob(SimpleQuartzJob.class).withIdentity("testJob","group").build();
//        SimpleTrigger trigger = TriggerBuilder.newTrigger()
//                .withIdentity("testTrigger", "group")
//                .startNow()
//                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
//                        .withIntervalInSeconds(1).
//                                repeatForever()).build();CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("testTrigger", "group").startNow().withSchedule(CronScheduleBuilder.cronSchedule("*/1 * * * * ?")).build();StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();Scheduler scheduler = stdSchedulerFactory.getScheduler();scheduler.start();scheduler.scheduleJob(jobDetail,trigger);}
}

五、Spring Boot中任务调度

在Spring Boot中开发定时任务需要在启动类上增加一个@EnableScheduling注解来开启定时任务功能。

其次,使用@Component注解标注一个类,在其需要定时执行的方法上添加@Scheduled注解。

@Component
public class TestScheduled {@Scheduled(fixedDelay = 3000)public  void test1(){System.out.println(LocalDateTime.now()+"  fixedDelay");}@Scheduled(fixedRate = 5000)public  void test2(){System.out.println(LocalDateTime.now()+"  fixedRate");}@Scheduled(cron = "*/1 * * * * ?")public  void test3(){System.out.println(LocalDateTime.now()+"  cron");}
}
@Scheduled中的参数如下:@Scheduled(fixedDelay = 3000):上次执行完毕后时间后3秒再次执行。@Scheduled(fixedRate = 5000):上次开始执行时间点后5秒再次执行。@Scheduled(cron = "*/1 * * * * ?"):按照cron表达式规则执行。

谈谈任务调度的四种实现方式相关推荐

  1. 简单谈谈OAuth 2.0的四种认证方式

    简单谈谈OAuth 2.0的四种认证方式 一.基本认识 1.1 OAuth认证中的四种角色 二.认证方式 2.1 授权码认证 2.2 简化认证 2.3 密码认证 2.4 客户端认证 一.基本认识 在小 ...

  2. RxJS的另外四种实现方式(一)——代码最小的库

    2019独角兽企业重金招聘Python工程师标准>>> 接上篇RxJS的另外四种实现方式(序) 起因 想到这个库的原因,是看了callbag库想到的,callbag库的原理大家可以自 ...

  3. JAVA四种引用方式

    JAVA四种引用方式: java.lang.ref: 强引用(直接变量赋值) 软引用(SoftReference): 只有在要发生OOM错误之前才会回收掉老的软引用对象,应用场景主要防止内存溢出.(缓 ...

  4. 矩阵乘法的四种理解方式

    先介绍向量的两种运算,一个行向量乘以一个列向量称作向量的内积,又叫作点积,结果是一个数: 一个列向量乘以一个行向量称作向量的外积,外积是一种特殊的克罗内克积,结果是一个矩阵, 假设和b分别是一个行向量 ...

  5. 【Android】android开发之splash闪屏页的四种实现方式,启动页的实现教程。

    2019独角兽企业重金招聘Python工程师标准>>> 作者:程序员小冰,GitHub主页: https://github.com/QQ986945193 新浪微博:http://w ...

  6. sqlserver的四种分页方式

    第一种:ROW_NUMBER() OVER()方式 select * from ( select *, ROW_NUMBER() OVER(Order by ArtistId ) AS RowId f ...

  7. 【Python基础】Python爬虫的两套解析方法和四种信息提取方式

    Python爬虫 Author:Iouwill Machine Learning Lab 分享一篇往日旧文章,非常实用. 对于大多数朋友而言,爬虫绝对是学习python的最好的起手和入门方式.因为爬虫 ...

  8. OAuth2.0的四种授权方式

    在OAuth2.0中,OAuth2.0 provider负责保护暴露在外的资源,第三方应用客户端Client可以独立的或代表用户Owner来访问这些受保护的资源,provider提供token令牌的管 ...

  9. php xml 四种,xml中常见的四种解析方式是什么?

    xml解析方式有:1.DOM解析方法,可以对xml文档进行修改操作:2.SAX解析方法,解析速度快,占用内存少:3.JDOM解析方法,查找方便:4.DOM4J解析方法,解析XML的速度快. 在XML的 ...

  10. 对require四种引入方式的认识

    对require四种引入方式的认识: 转载于:https://www.cnblogs.com/461770539-qq/p/9357485.html

最新文章

  1. 安卓模拟器BlueStacks 安装使用教程(图解)
  2. SpringBoot - 优雅的处理【长事务】
  3. TopFreeTheme精选免费模板【20130701.特别版】
  4. python six库_six库 解决python2的项目如何能够完全迁移到python3
  5. vue 怎么清空依赖_vuejs如何在把对象所有属性清空?
  6. bash: vim: command not found
  7. 建立企业内部maven服务器并使用Android Studio发布公共项目
  8. 那些炫酷的特效--QQ空间+VUE
  9. 四轮定位和四轮动平衡有什么区别?
  10. AcWing 904. 虫洞(SPFA or Djakarta or bellman判负环)
  11. 论Webstorm汉化后无法打开配置
  12. vue 判断是否是微信浏览器
  13. adb命令刷机vivox20_vivo手机变砖 刷机手机端口连上显示adb
  14. 云计算与大数据之间的关系
  15. 关于计算机的想象类作文,想象类作文范文
  16. instant-ngp总结
  17. latex中极限号下边怎么打_latex 极限下标
  18. 基于SSH会员积分消费管理系统
  19. 网络加速技术浅析(二)
  20. Linux系统如何更新升级

热门文章

  1. plotyy函数_plotyy函数参数设置
  2. emi滤波matlab,EMI滤波器的作用和种类
  3. JVM 为什么使用元空间替换了永久代?
  4. 静态IP、动态IP、ADSL拨号和DNS这几者你分得清吗?
  5. 有IPV6无法登录IPV6网站*
  6. 如何跳过计算机配置直接开机,WIN7开机怎么跳过欢迎界面_win7怎样跳过电脑开机欢迎界面-win7之家...
  7. 亚马逊Rating和Review的这些区别你知多少?
  8. 【web攻防】CVE-2020-10487 tomcat 文件包含漏洞 docker 复现学习
  9. python太阳代码_用86行Python代码模拟太阳系
  10. 在解压缩某些文件时出现问题检查计算机上,rar文件解压缩失败解压末端出现错误的解决方法...