定时任务几种实现方式

Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务,没怎么用过就不说了。

Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。

java的线程池类ScheduledExecutorService也可以实现一些简单的定时任务,周期性任务。

Quartz是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,可以方便的分布式部署、便捷的监控和管理任务,适合任务很多的情况。

Spring Scheduler注解方式实现

代码还是挺少的

@Component

public class SchedulerPractice{

// @Scheduled(fixedDelay=60000)

@Scheduled(cron = "0 0/1 * * * ?")
 public void execute() {
 logger.info("every one minute------");
 }

}

1

2

3

4

5

配置文件

1

2

3

4

5

6

7

pool-size=”2” 有多个任务可以配置以线程池执行

注解使用方式

@Scheduled(cron = "${cron_expression}")

1

分布式多实例运行

scheduler与web配置在一起,在高可用的情况下,如果有多个web容器实例,scheduler会在多个实例上同时运行。

解决办法:

使用写死服务器Host的方式执行task,存在单点风险,负载均衡手动完成。(或者一台代码中配置任务,其他不配置任务)

在task的基类加入一些逻辑,当开始运行时,将状态(运行机器的IP、时间等)写入数据库、缓存(redis)或者zk,运行结束时重置状态。其它实例看到有这样的数据,就直接返回。带来的问题是:

一定要保证结束运行后将状态重置,否则下一个运行周期,所有的task都会返回的。

因为读写状态并非原子操作,偶尔也会发生task同时运行的事。

使用zk分布式锁,比如在任务执行方法上自定义注解,在注解中配置锁在zk的路径,在该注解上自定义个拦截器,在拦截器中获取zk锁。

Java线程池ScheduledExecutorService

示例代码如下

public void cronThread(){

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);

scheduledThreadPool.scheduleWithFixedDelay(new ThreadPractice(), 0, 3, TimeUnit.SECONDS);

}

1

2

3

4

5

6

new ThreadPractice()是一个实现了Runnable的类。

ScheduledExecutorService 类有两个方法

public ScheduledFuture> scheduleAtFixedRate(Runnable command,

long initialDelay,

long period,

TimeUnit unit)

public ScheduledFuture> scheduleWithFixedDelay(Runnable command,

long initialDelay,

long delay,

TimeUnit unit)

1

2

3

4

5

6

7

8

9

这两个方法和@scheduled 注解中的fixedDelay和fixedRate类似。

Quartz

Quartz框架是一个全功能、开源的任务调度服务,可以集成几乎任何的java应用程序—从小的单片机系统到大型的电子商务系统。可以方便的分布式部署、便捷的监控和管理任务,Quartz可以执行上千上万的任务调度。

核心概念

Quartz核心的概念:scheduler任务调度、Job任务、Trigger触发器、JobDetail任务细节

Job任务:其实Job是接口,其中只有一个execute方法, 只要实现此接口,实现execute方法即可。

JobDetail:任务细节,Quartz执行Job时,需要新建个Job实例,但是不能直接操作Job类,所以通过JobDetail来获取Job的名称、描述信息。

Trigger触发器:执行任务的规则;比如每天,每小时等。触发器有SimpleTrigger和CronTrigger,这个触发器实现了Trigger接口。对于复杂的时间表达式来说,比如每个月15日上午几点几分,使用CronTrigger,对于简单的时间来说,比如每天执行几次,使用SimpleTrigger。

scheduler任务调度:是最核心的概念,需要把JobDetail和Trigger注册到scheduler中,才可以执行。

quartz单机示例

使用的quartz的jar的版本是:2.2.1 ,低版本的核心类可能有些不同。

job类

public class MyJob implements Job {

@Override

//把要执行的操作,写在execute方法中

public void execute(JobExecutionContext arg0) throws JobExecutionException {

System.out.println(“test Quartz"+new Date());

}

}

1

2

3

4

5

6

7

8

测试代码

@Test

public void startJobTest() {

SchedulerFactory schedulerfactory = new StdSchedulerFactory();

Scheduler scheduler = null;

try {

// 通过schedulerFactory获取一个调度器

scheduler = schedulerfactory.getScheduler();

// 创建jobDetail实例,绑定Job实现类

// 指明job的名称,所在组的名称,以及绑定job类

JobDetail job = JobBuilder.newJob(ImageTableMonitorJob.class).withIdentity("job1", "jgroup1").build();

// 定义调度触发规则

// 使用simpleTrigger规则

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("simpleTrigger", "triggerGroup")

.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withRepeatCount(8)).startNow().build();

// 使用cornTrigger规则 每天10点42分

// Trigger trigger= TriggerBuilder.newTrigger().withIdentity("simpleTrigger", "triggerGroup")

// .withSchedule(CronScheduleBuilder.cronSchedule("0 42 10 * * ? *"))

// .startNow().build();

// 把作业和触发器注册到任务调度中

scheduler.scheduleJob(job, trigger);

// 启动调度

scheduler.start();

} catch (Exception e) {

// e.printStackTrace();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

spring提供了对quartz的整合,可以通过 org.springframework.scheduling.quartz.SchedulerFactoryBean 注入scheduler调度器,并且对调度器做些配置,比如使用线程池,并配置线程数量等。配置示例如下。

1

2

3

4

5

6

7

8

9

Quartz分布式原理

Quartz的集群部署方案在架构上是分布式的,没有负责集中管理的节点,而是利用数据库锁的方式来实现集群环境下进行并发控制。分布式部署时需要保证各个节点的系统时间一致。没弄过,就不细说了。

Quartz数据库核心表QRTZ_LOCKS中有5条记录CALENDAR_ACCESS,JOB_ACCESS,MISFIRE_ACCESS,STATE_ACCESS,TRIGGER_ACCESS 代表5把锁,分别用于实现多个Quartz Node对Job、Trigger、Calendar访问的同步控制。

cron表达式

字段 允许值 允许的特殊字符

秒 0-59 , - * /

分 0-59 , - * /

小时 0-23 , - * /

日期 1-31 , - * ? / L W C

月份 1-12 或者 JAN-DEC , - * /

星期 1-7 或者 SUN-SAT , - * ? / L C #

年(可选) 留空, 1970-2099 , - * /

- 区间

* 通配符

? 你不想设置那个字段

1

2

3

4

5

6

7

8

9

10

11

12

13

下面列出一些实例

CRON表达式 含义

"0 0 12 * * ?" 每天中午十二点触发

"0 15 10 ? * *" 每天早上10:15触发

"0 15 10 * * ?" 每天早上10:15触发

"0 15 10 * * ? *" 每天早上10:15触发

"0 15 10 * * ? 2005" 2005年的每天早上10:15触发

"0 * 14 * * ?" 每天从下午2点开始到2点59分每分钟一次触发

"0 0/5 14 * * ?" 每天从下午2点开始到2:55分结束每5分钟一次触发

"0 0/5 14,18 * * ?" 每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发

"0 0-5 14 * * ?" 每天14:00至14:05每分钟一次触发

"0 10,44 14 ? 3 WED" 三月的每周三的14:10和14:44触发

"0 15 10 ? * MON-FRI" 每个周一、周二、周三、周四、周五的10:15触发

1

2

3

4

5

6

7

8

9

10

11

12

参考资料

java 获取scheduler_Spring Scheduler定时任务 + Quartz相关推荐

  1. 定时任务-Quartz、Mycat简单入门、Linux下安装MySQL、Linux下安装MyCAT、Mycat的数据库分片、Mycat读写分离

    表现层:页面 后台管理系统.商城门户.搜索系统.订单系统.商品详情系统.购物车系统 中间件:dubbo 系统之间的通信,服务的统计,rpc协议远程过程调用 同步通信 服务层:实现具体的业务逻辑 商品服 ...

  2. SpringBoot系列:Spring Boot集成定时任务Quartz

    一.关于Quartz Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.在java企业级应用中,Q ...

  3. Spring Boot定时任务-Quartz介绍

    SpringBoot如何整合第三方定时任务框架,SpringBoot整合Quartz定时任务框架,我们主要来了解一下Quartz的一个介绍,以及对于Quartz使用的一个基本思路,我们先来看Quart ...

  4. Spring中定时任务Quartz集群配置学习

    Spring中定时任务Quartz集群配置学习 原来配置的Quartz是通过spring配置文件生效的,发现在非集群式的服务器上运行良好,但是将工程部署到水平集群服务器上去后改定时功能不能正常运行,没 ...

  5. 定时任务_定时任务Quartz入门

    前言 Quartz是一个定时任务框架,即可以在程序运行期间,定时定期的做出些什么事情,比如发邮件,重启机器,清除缓存等等. java.util.Timer也可以做到这些功能,但是Quartz框架毕竟是 ...

  6. java timertask 定时_Java定时任务--Timer和TimerTask

    1.程序和编程 我们知道,计算机程序是一组计算机能识别和执行的指令,运行于电子计算机上,满足人们某种需求的信息化工具. 简单来说程序在本质上是指令的集合,而编程从字面上来讲就是编写这些指令集合(程序) ...

  7. spring -boot定时任务 quartz 基于 MethodInvokingJobDetailFactoryBean 实现

    spring 定时任务 quartz 基于  MethodInvokingJobDetailFactoryBean 实现 依赖包 如下 <dependencies><dependen ...

  8. Spring Boot定时任务-Quartz基本使用

    我们在项目当中去使用一个Quartz,主要是了解Quartz的一个基本使用方式,Quartz的基本使用方式,首先打开我们的eclipse,使用SpringBoot去整合我们的Quartz,我们就不加S ...

  9. java 获取service_Java service层获取HttpServletRequest工具类的方法

    Java service层获取HttpServletRequest工具类的方法 大家都知道 能在Controller/action层获取HttpServletRequest,但是这里给大家备份的是从代 ...

最新文章

  1. re模块与正则表达式
  2. python编程题-基本编程题 --python
  3. hive--udf函数(开发-4种加载方式)
  4. 数据中心胶体电池的使用寿命
  5. 如何正确使用Python临时文件
  6. 《异构信息网络挖掘: 原理和方法(1)》一第2章 基于排名的聚类
  7. linux运维之道基础命令,Linux运维之道(7)——Linux管理类命令
  8. POI处理超过65536条记录
  9. MOSSE相关滤波算法学习笔记
  10. Tbase 源码 (三)
  11. python实现分层随机抽样算法_python分层随机抽样
  12. 融云CTO杨攀:以技术为先导 全面聚焦“互联网通信云”
  13. 联想产品标准保修承诺
  14. LeetCode-剑指Offe-32-1-从上到下打印二叉树
  15. iVMS-4200 Vs区别_理科与工科有什么区别?如何判断自己适合学那个?
  16. 自定义View基础:Android中的颜色和颜色混合
  17. codeforces 549F Yura and Developers(分治、启发式合并)
  18. 多相机BEV感知表达
  19. MODIS 数据产品预处理
  20. linux 超级作用域,linux dhcp超级作用域配置

热门文章

  1. AI环境搭建步骤(Windows环境)
  2. 你生日那天的宇宙什么样子知道?我全部给你吧!
  3. 安全驾驶学习实践总结
  4. Lesson 7 Too late 为时太晚
  5. All in AI,现在开始算不算太晚?
  6. matlab中有omp文件,用MATLAB实现OMP恢复算法
  7. 操作系统学习之系统调用
  8. InternetOpen, InternetOpenUrl, InternetReadFile 获取网页源代码
  9. InternetOpen/InternetConnect/函数
  10. 流下了不学无术的泪水:今天你刷题了吗(二)