Timer

JDK自带的Timer类,允许调度一个TimerTask任务。

Demo:

/**
* Timer测试类
*/
public class TimerDemo {
public static void main(String[] args) {
// 创建定时器
Timer timer = new Timer(); // 添加调度任务
// schedule(TimerTask task, Date time); 特定时间 time 执行
// timer.schedule(new MyTask(), new Date(System.currentTimeMillis() + 1000)); // schedule(TimerTask task, long delay); //延迟 delay毫秒 执行 task
// timer.schedule(new MyTask(), 1000); // schedule(TimerTask task, long delay, long period) 延迟 delay毫秒 执行并每隔 period毫秒 执行一次
// timer.schedule(new MyTask(), 1000, 5000); // schedule(TimerTask task, Date time, long period); 特定时间 time 执行并每隔 period毫秒 执行一次
timer.schedule(new MyTask(), new Date(System.currentTimeMillis() + 1000), 5000); }
}
/**
* 具体执行的任务
*/
public class MyTask extends TimerTask {
/**
* The action to be performed by this timer task.
*/
public void run() {
System.out.println("执行时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}

Spring Task:

Spring3.0以后自主开发的定时任务工具Spring Task,支持线程池,可以高效处理许多不同的定时任务,除spring相关的包外不需要额外的包,支持注解和配置文件两种形式。 但不能处理过于复杂的任务 。

基于配置的Demo:

定时任务类:

/**
* spring执行任务的类
*/
public class SpringTask {
public void show1() {
System.out.println("show1:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
} public void show2() {
System.out.println("show2:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}

配置文件spring-schedule.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <bean id="springTask" class="com.zy.springtask.SpringTask"></bean>
<!--注册调度任务-->
<task:scheduled-tasks>
<!--延迟1秒 执行任务-->
<!--<task:scheduled ref="springTask" method="show1" fixed-delay="1000" />--> <!--固定速度3秒 执行任务-->
<!--<task:scheduled ref="springTask" method="show2" fixed-rate="3000" />--> <!--
使用cron表达式 指定触发时间
spring task 只支持6位的cron表达式 秒 分 时 日 月 星期
-->
<task:scheduled ref="springTask" method="show1" cron="1-10 * * ? * *" />
</task:scheduled-tasks> <!--执行器配置-->
<task:executor id="threadPoolTaskExecutor" pool-size="10" keep-alive="5"></task:executor> <!--调度器配置-->
<task:scheduler id="threadPoolTaskScheduler" pool-size="10"></task:scheduler>
</beans>

基于注解的Demo:

定时任务类:

/**
* spring执行任务的类
*/
@Component
public class SpringAnnoTask {
@Scheduled(cron = "1-10 * * * * ? ")//每分钟的1-10秒每秒执行一次
public void show1() {
System.out.println("show1:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
} @Scheduled(cron = "0/10 * * * * ? ")//每10秒执行一次
public void show2() {
System.out.println("show2:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}

配置文件spring-schedule.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <!--启用注解-->
<task:annotation-driven></task:annotation-driven> <bean id="springAnnotationTask" class="com.zy.springtask.SpringAnnoTask"></bean>
</beans>

Quartz

这个就厉害了,这篇文章只能简单介绍个入门案例,如果需要深入研究请自行查看官方文档或者网上找些系列的文章。w3cschool文档

  Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是完全由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。

特点:

  • 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;
  • 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;
  • 分布式和集群能力,Terracotta 收购后在原来功能基础上作了进一步提升。
  • 另外,作为 Spring 默认的调度框架,Quartz 很容易与 Spring 集成实现灵活可配置的调度功能。

核心元素 :

  • Scheduler: 任务调度器,是实际执行任务调度的控制器。在spring中通过SchedulerFactoryBean封装起来。
  • Trigger :触发器,用于定义任务调度的时间规则,有SimpleTrigger,CronTrigger,DateIntervalTrigger和NthIncludedDayTrigger,其中CronTrigger用的比较多,本文主要介绍这种方式。CronTrigger在spring中封装在CronTriggerFactoryBean中。
  • Calendar:它是一些日历特定时间点的集合。一个trigger可以包含多个Calendar,以便排除或包含某些时间点。
  • Job :任务,是一个接口,只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在JobDataMap实例中。实现Job接口的任务,默认是无状态的,若要将Job设置成有状态的,在quartz中是给实现的Job添加@DisallowConcurrentExecution注解(以前是实现StatefulJob接口,现在已被Deprecated),在与spring结合中可以在spring配置文件的job detail中配置concurrent参数。
  • JobDetail :任务信息,用来描述Job实现类及其它相关的静态信息,如Job名字、关联监听器等信息。在spring中有JobDetailFactoryBean和 MethodInvokingJobDetailFactoryBean两种实现,如果任务调度只需要执行某个类的某个方法,就可以通过MethodInvokingJobDetailFactoryBean来调用。

Trigger触发器 :

  • SimpleTrigger :在一个指定时间段内执行一次作业任务或是在指定时间间隔内执行多次作业任务;
  • CronTrigger :基于日历的作业调度器,而不是像SimpleTrigger那样精确指定间隔时间,比SimpleTrigger更常用。

简单案例:

jar包依赖:

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

具体定时任务需要执行的类:

/**
* 具体执行的任务 实现Job接口
*/
public class MyDemoJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // 当前时间
System.out.println("执行时间:" + sf.format(new Date())); // 获取Trigger
Trigger trigger = jobExecutionContext.getTrigger();
// 通过trigger获取job标识
JobKey jobKey = trigger.getJobKey();
System.out.println("Job's key:" + "name:" + jobKey.getName() + "\tgroup:" + jobKey.getGroup());
// getClass();
System.out.println("Start time : " + sf.format(trigger.getStartTime()));
// System.out.println("End time : " + sf.format(trigger.getEndTime()));
}
}

基础Demo:

/**
* 基础触发器调度程序
*/
public class BaseScheduler {
public static void main(String[] args) {
try {
// 1. 创建一个JodDetail实例 将该实例与具体要执行的job类 MyDemoJob.class绑定
JobDetail jobDetail = JobBuilder.newJob(MyDemoJob.class) // 定义Job类为MyDemoJob类(具体执行定时任务的内容)
.withIdentity("myJob", "default") // 定义name/group
.build(); // 2. 定义一个Trigger,10秒后执行
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); // 2.1 设置开始时间
Date startTime = new Date();
startTime.setTime(startTime.getTime() + 10000L);
// 2.2 设置结束时间
// Date endTime = new Date();
//endTime.setTime(endTime.getTime() + 20000L); Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger", "default")// 定义名字和组
.startAt(startTime)
//.endAt(endTime)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())
// 上面这句的意思是 这个定时器每5秒执行一次 直到山峰没有棱角 河水不再流 详细使用请查看withSchedule的参数设置
.build(); // 3. 创建scheduler 从StdSchedulerFactory工厂中获取
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); // 4. 将jobDetail和trigger加入这个调度(注册 任务详情和触发器)
scheduler.scheduleJob(jobDetail, trigger); // 5. 启动scheduler
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

基于SimpleTrigger的Demo:

/**
* SimpleTrigger 简单触发器调度程序
*/
public class SimpleTriggerScheduler {
public static void main(String[] args) {
try {
// 1. 创建一个JodDetail实例
JobDetail jobDetail = JobBuilder.newJob(MyDemoJob.class)
.withIdentity("myJob")
.build(); // 2. 定义一个Trigger
Date startTime = new Date();
startTime.setTime(startTime.getTime() + 5000L);
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")// 定义名字和组
.startAt(startTime)
.build(); // 3. 创建scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); // 4. 将jobDetail和trigger加入这个调度(注册 任务详情和触发器)
scheduler.scheduleJob(jobDetail, trigger); // 5. 启动scheduler
scheduler.start(); } catch (Exception e) {
e.printStackTrace();
}
}
}

基于CronTrigger的Demo:

/**
* CronTrigger 基于Cron表达式的触发器调度程序
*/
public class CronTriggerScheduler {
public static void main(String[] args) {
try {
// 1. 创建一个JodDetail实例
JobDetail jobDetail = JobBuilder.newJob(MyDemoJob.class)
.withIdentity("myJob") // 定义name/group
.build(); // 2. 定义一个Trigger 使用Cron表达式来控制运行
CronTrigger trigger = (CronTrigger) TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.withSchedule( //定义任务调度的时间间隔和次数
CronScheduleBuilder
.cronSchedule("0/10 * * * * ? ")//每10秒运行一次
)
.build(); // 3. 创建scheduler
SchedulerFactory sfact = new StdSchedulerFactory();
Scheduler scheduler = sfact.getScheduler(); // 4. 将jobDetail和trigger加入这个调度(注册 任务详情和触发器)
scheduler.scheduleJob(jobDetail, trigger); // 5. 启动scheduler
scheduler.start(); } catch (Exception e) {
e.printStackTrace();
}
}
}

Spring整合Quartz的简单案例

PS:Cron表达式介绍

Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式:

​ (1)Seconds Minutes Hours DayofMonth Month DayofWeek Year

​ (2)Seconds Minutes Hours DayofMonth Month DayofWeek

各个字段的含义:

字段 允许值 允许的特殊字符
秒(Seconds) 0~59的整数 , - * /    四个字符
分(Minutes 0~59的整数 , - * /    四个字符
小时(Hours 0~23的整数 , - * /    四个字符
日期(DayofMonth 1~31的整数(但是你需要考虑你月的天数) ,- * ? / L W C     八个字符
月份(Month 1~12的整数或者 JAN-DEC , - * /    四个字符
星期(DayofWeek 1~7的整数或者 SUN-SAT (1=SUN) , - * ? / L C #     八个字符
年(可选,留空)(Year 1970~2099 , - * /    四个字符

每一个域都使用数字,但还可以出现如下特殊字符,它们的含义是:

(1)*:表示匹配该域的任意值。假如在Minutes域使用*, 即表示每分钟都会触发事件。

(2)?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。
例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。 (3)-:表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次 (4)/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次. (5),:表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。 (6)L:表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。 (7)W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。
例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;
如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。 (8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。 (9)#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。

java定时任务实现的几种方式(Timer、Spring Task、Quartz)的更多相关文章

  1. JAVA定时任务实现的几种方式

    近日项目开发中需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息,借此机会整理了一下定时任务的几种实现方式,由于项目采用spring框架,所以我都将结合spring框架来介绍. 一 ...

  2. Java创建线程的四种方式

    Java创建线程的四种方式 1.继承Thread类创建线程 定义Thread类的子类,并重写该类的run方法,run()方法的内容就是该线程执行的内容 创建Thread子类的实例,即创建了线程对象. ...

  3. 如何实现有返回值的多线程 JAVA多线程实现的三种方式

    可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口.执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable ...

  4. Java中创建对象的几种方式

    Java中创建对象的五种方式: 作为java开发者,我们每天创建很多对象,但是我们通常使用依赖注入的方式管理系统,比如:Spring去创建对象,然而这里有很多创建对象的方法:使用New关键字.使用Cl ...

  5. java产生随机数的几种方式

    java产生随机数的几种方式 一.在j2se里我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以把他乘以一定的数,比如说乘以100,他 ...

  6. Java读写文件的几种方式

    自工作以后好久没有整理Java的基础知识了.趁有时间,整理一下Java文件操作的几种方式.无论哪种编程语言,文件读写操作时避免不了的一件事情,Java也不例外.Java读写文件一般是通过字节.字符和行 ...

  7. JAVA解析XML的四种方式

    java解析xml文件四种方式 1.介绍 1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这 ...

  8. Java添加事件的四种方式

    Java添加事件的几种方式(转载了codebrother的文章,做了稍微的改动) /** * Java事件监听处理——自身类实现ActionListener接口,作为事件监听器 * * @author ...

  9. java解析xml的几种方式

    java解析xml的几种方式 DOM DOM的全称是Document ObjectModel,也即文档对象模型.在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称D ...

随机推荐

  1. SVN的详细简单操作

    SVN服务器搭建和使用(一)  http://www.cnblogs.com/xiaobaihome/archive/2012/03/20/2407610.html SVN服务器搭建和使用(二) ht ...

  2. fn project AWS Lambda 格式 functions

      Creating Lambda Functions Creating Lambda functions is not much different than using regular funct ...

  3. gogs docker 安装

     1.  gogs 镜像      docker pull gogs/gogs    2.  mysql    docker mysql    3.  本地数据卷配置 mkdir gogs & ...

  4. Yii CDbCriteria类中方法

    $criteria = new CDbCriteria; //select $criteria->select = '*';//默认* $criteria->select = 'id,na ...

  5. 通过IHttpModule,IHttpHandler扩展IIS

    IIS对Http Request的处理流程 当Windows Server收到从浏览器发送过来的http请求,处理流程如下(引用自官方文档): 最终请求会被w3wp.exe处理,处理过程如下: 左边蓝 ...

  6. maven编译问题:maven编译成功,eclipse文件未编译

    我们先来看一个正常的编译流程: 1.从svn上检出一个项目: 2.看该工程是否为maven项目,不是则先转为maven项目:右键单击项目,选择configure->Convert to Mave ...

  7. C语言通过地址传递参数

    // 正确 #include <stdio.h> struct para { int a; int b; }; struct para test = { .a = , .b = , }; ...

  8. 安装jenkins 的时候 记录默认密码文件为空的情况

    1.把文件的权限改成 chmod 777 .jenkins/secrets/initialAdminPassword  然后再使用编辑器打开,密码就出来的 密码文件的地址 /var/root/.hud ...

  9. 命令行调用远程dubbo服务

    有时需要对dubbo服务做个简单的测试,或者想看下某个dubbo服务类所提供的方法,可以直接在命令行通过telnet的方式来查看和调用dubbo服务,方法如下: telnet 127.0.0.1 20 ...

  10. Wireshark捕获非加密的数据包

    启动监听模式 root@sch01ar:~# airmon-ng start wlan0 启动Wireshark工具 root@sch01ar:~# wireshark 选择接口,这里选择wlan0m ...