摘要
我们在项目中经常会处理一些定时更新的数据,比如定期删除缓存的token,设置订单的有效时间,利用定时任务处理日志及一些缓存,或者定期做更新数据等一系列的复杂业务;在这里我做了一份总结,希望能帮到大家;如果有不准确的地方希望能够提供宝贵的建议
代码下载地址:https://github.com/tazhigang/TimedTask.git
1、线程实现定时任务
话不多说,直接上代码
package com.ittzg.task;
/**
* @Author: ittzg
* @CreateDate: 2018/12/7
* @Description: 线程实现定时任务
* 运行环境是JDK8 使用lambda表达式 大家可以下去看看
*/
public class TimedTaskDemo01 {
public static void main(String[] args) {
new Thread(() ->{
int time = 1;
while(true){
//每5秒钟执行一次
System.out.println("Perform the task every 5 secouds!\t"+(time++)+"\t"+new Date());
try {Thread.sleep(5000);} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
运行结果
Perform the task every 5 secouds! 1 Fri Dec 07 14:59:08 GMT+08:00 2018
Perform the task every 5 secouds! 2 Fri Dec 07 14:59:13 GMT+08:00 2018
Perform the task every 5 secouds! 3 Fri Dec 07 14:59:18 GMT+08:00 2018
......
2、Timer实现定时任务
package com.ittzg.task;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* @Author: ittzg
* @CreateDate: 2018/12/7 13:17
* @Description: 使用Timer完成定时任务
*/
public class TimedTaskDemo02 {
public static void main(String[] args) throws ParseException {
System.out.println("程序执行时间"+new Date());
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("this is a timerTask /n 目标任务执行时间:"+new Date());
}
};
Timer timer = new Timer();
/*//1.schedule(TimerTask task, Date time) 表示在指定的时间点执行task
Date date = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse("2018-12-07 13:57:50");
timer.schedule(timerTask,date);*/
/* //2.schedule(TimerTask task, long delay) 表示延迟delay毫秒以后执行task
timer.schedule(timerTask,5000); //5000表示5秒*/
/*//3.schedule(TimerTask task, Date firstTime, long period) 表示任务从date时候
//首次开始执行,以后每period 毫秒执行一次
Date date1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse("2018-12-07 14:18:30");
timer.schedule(timerTask,date1,5000);*/
//4.schedule(TimerTask task, long delay, long period)
// 表示任务从delay毫秒时候开始首次执行,以后每period 毫秒执行一次
timer.schedule(timerTask,5000,5000);
//5.scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
// 表示任务从date时候首次开始执行,以后每period 毫秒执行一次
//6.scheduleAtFixedRate(TimerTask task, long delay, long period)
// 表示任务从delay毫秒时候开始首次执行,以后每period 毫秒执行一次
}
}
......
以上方法是用白话描述的,方便大家理解
这里说明一下
scheduleAtFixedRate(TimerTask task, Date firstTime, long period)与
schedule(TimerTask task, Date firstTime, long period)的功能看起来一样但是却有所不同
我们来参考API说明一下
1. schedule方法在api中给出了如下解释
In fixed-delay execution, each execution is scheduled relative to the actual
execution time of the previous execution. If an execution is delayed for any
reason (such as garbage collection or other background activity), subsequent
executions will be delayed as well. In the long run, the frequency of execution
will generally be slightly lower than the reciprocal of the specified period
(assuming the system clock underlying Object.wait(long) is accurate). As a
consequence of the above, if the scheduled first time is in the past, it is
scheduled for immediate execution.
大致的意思是:在固定的延迟执行中,每一次执行都是在初次执行的基础上,按照预定时间对任务
进行调度,如果由于任何原因所导致的执行延迟(比如垃圾回收,后台干扰运行),
则后续执行的任务也将延迟;从长远来看,执行频率通常会略低于指定时间段的
倒数。除此之外,如果计划的第一时间是过去的,则计划立即执行。
2.scheduleAtFixedRate方法在api中给出了如下解释
In fixed-rate execution, each execution is scheduled relative to the scheduled
execution time of the initial execution. If an execution is delayed for any reason
(such as garbage collection or other background activity), two or more executions
will occur in rapid succession to "catch up." In the long run, the frequency of
execution will be exactly the reciprocal of the specified period (assuming the
system clock underlying Object.wait(long) is accurate).
大致的意思是:在固定的延迟执行中,每一次执行都是在初次执行的基础上,按照预定时间对任务
进行调度,如果由于任何原因所导致的执行延迟(比如垃圾回收,后台干扰运行),
则scheduleAtFixedRate方法将快速连续地出现两次或更多的执行,从而使后续执行能
够“追赶上来”。从长远看,执行的频率很接近指定的周期。
3、SpringBoot实现定时任务(注解开发)
1.创建springboot的maven项目
1> 项目包结构
2>pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ittzg</groupId>
<artifactId>schema</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>schema</name>
<description>this is timedTask</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.定时任务类
package com.ittzg.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @Author: ittzg
* @CreateDate: 2018/12/7 20:55
* @Description:
*/
@Component //一定要加,否则启动时不会创建该类,更扫描不到定时任务
public class TimedTaskDemo {
//cron生成器地址 http://cron.qqe2.com/
// 注意生成的cron 在运行时会出现
//Cron expression must consist of 6 fields (found 7 in "0 * * * * ? *")
// 这时候果断把最后一位去掉
@Scheduled(cron = "0/5 * * * * ?")
public void printMsg(){
//此处写你的业务代码
System.out.println("这是一个定时任务\t" +new Date());
}
}
3.启动类
package com.ittzg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling //启动类一定不要忘记加这个注解,否则定时任务不会触发
public class SchemaApplication {
//如果不在TimedTaskDemo上加@Component,可以使用以下代码代替该注解
/*@Bean
public TimedTaskDemo getBean(){
return new TimedTaskDemo();
}*/
public static void main(String[] args) {
SpringApplication.run(SchemaApplication.class, args);
}
}
4.运行启动类结果
这是一个定时任务 Fri Dec 07 21:29:25 GMT+08:00 2018
这是一个定时任务 Fri Dec 07 21:29:30 GMT+08:00 2018
这是一个定时任务 Fri Dec 07 21:29:35 GMT+08:00 2018
这是一个定时任务 Fri Dec 07 21:29:40 GMT+08:00 2018
这是一个定时任务 Fri Dec 07 21:29:45 GMT+08:00 2018
......