1 简单介绍
1)什么是定时任务调度
2)Timer简介
打开jdk-zh说明文档查看即可
推荐看英文版本的
简单写个demo,感受一下timer的定时调度函数.schedule()(本人实践用的是idea,也可以用eclipse等,看个人喜好)
MyTimerTask.java
package com.java.study.timer;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask {
private String name;
public MyTimerTask(String inputname) {
name = inputname;
}
@Override
public void run() {
System.out.println("Current name is " + name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
MyTimer.java
package com.java.study.timer;
import java.util.Timer;
public class MyTimer {
public static void main(String[] args) {
// 1. 创建一个Timer实例
Timer timer = new Timer();
// 2. 创建一个MyTimerTask实例
String inputname = "hello timer";
MyTimerTask myTimerTask = new MyTimerTask(inputname);
// 3. 通过timer定时定频率调用myTimerTask的业务逻辑
// 定时即当前执行时间的2s之后;
// 定频率即之后每隔1s执行一次;
timer.schedule(myTimerTask, 2000L, 1000L);
}
}
执行效果:
3)基于上面的实践,来说说Timer的定时调度函数
schedule的四种用法:
实际操作一下试试看:
MyTimerTask.java
...
@Override
public void run() {
// 实现自己的业务逻辑 todo
// 以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间
// 如:2020-04-06 12:12:12
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Current time is " + simpleDateFormat.format(calendar.getTime()));
// 此处是demo只增加一个打印输出语句
System.out.println("Current name is " + name);
}
...
}
MyTimer.java
...
public class MyTimer {
public static void main(String[] args) {
...
/**
* 获取当前时间,并设置成距离当前时间3秒之后的时间
* 如:当前是2020-04-06 12:12:12
* 则设置后的时间则为2020-04-06 12:12:15
*/
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Real Current time is " + simpleDateFormat.format(calendar.getTime()));
// 当前时间被设置成距离当前时间3秒之后的时间
calendar.add(Calendar.SECOND, 3);
// ----------- schedule 的用法 -----------
/**
* 1、在时间等于或超过time的时候执行,且只执行一次task
* 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
*/
myTimerTask.setName("schedule_1 ======== ");
timer.schedule(myTimerTask, calendar.getTime());
}
}
实际效果:
实际操作一下试试看:
MyTimer.java
// ----------- schedule 的用法 -----------
/**
* 1、在时间等于或超过time的时候执行,且只执行一次task
* 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
*/
// myTimerTask.setName("schedule_1 ======== ");
// timer.schedule(myTimerTask, calendar.getTime());
/**
* 2、在时间等于或超过time的时候首次执行task
* 之后每隔period毫秒重复执行一次task
* 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
myTimerTask.setName("schedule 2 ========");
timer.schedule(myTimerTask, calendar.getTime(), 2000);
实际效果:
实际操作一下试试看:
MyTimer.java
// ----------- schedule 的用法 -----------
/**
* 1、在时间等于或超过time的时候执行,且只执行一次task
* 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
*/
// myTimerTask.setName("schedule_1 ======== ");
// timer.schedule(myTimerTask, calendar.getTime());
/**
* 2、在时间等于或超过time的时候首次执行task
* 之后每隔period毫秒重复执行一次task
* 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
// myTimerTask.setName("schedule 2 ========");
// timer.schedule(myTimerTask, calendar.getTime(), 2000);
/**
* 3、等待delay毫秒后执行且只执行一次task
* 如:现在是2020-04-06 12:12:15,delay=1000
* 那么会在2020-04-06 12:12:16 执行一次task--打印时间的任务
*/
myTimerTask.setName("schedule 3 ========");
timer.schedule(myTimerTask, 1000);
实际效果:
实际操作一下试试看:
MyTimer.java
// ----------- schedule 的用法 -----------
/**
* 1、在时间等于或超过time的时候执行,且只执行一次task
* 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
*/
// myTimerTask.setName("schedule_1 ======== ");
// timer.schedule(myTimerTask, calendar.getTime());
/**
* 2、在时间等于或超过time的时候首次执行task
* 之后每隔period毫秒重复执行一次task
* 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
// myTimerTask.setName("schedule 2 ========");
// timer.schedule(myTimerTask, calendar.getTime(), 2000);
/**
* 3、等待delay毫秒后执行且只执行一次task
* 如:现在是2020-04-06 12:12:15,delay=1000
* 那么会在2020-04-06 12:12:16 执行一次task--打印时间的任务
*/
// myTimerTask.setName("schedule 3 ========");
// timer.schedule(myTimerTask, 1000);
/**
* 4、等待delay毫秒首次执行task 和2类似
* 之后每隔period毫秒重复执行一次task
* 如:现在是2020-04-06 12:12:15,delay=1000 ms
* 那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
myTimerTask.setName("schedule 4 ========");
timer.schedule(myTimerTask,1000, 2000);
实际效果:
scheduleAtFixedRate的两种用法:
实际操作一下试试看:
MyTimer.java
// ----------- schedule 的用法 -----------
/**
* 1、在时间等于或超过time的时候执行,且只执行一次task
* 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
*/
// myTimerTask.setName("schedule_1 ======== ");
// timer.schedule(myTimerTask, calendar.getTime());
/**
* 2、在时间等于或超过time的时候首次执行task
* 之后每隔period毫秒重复执行一次task
* 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
// myTimerTask.setName("schedule 2 ========");
// timer.schedule(myTimerTask, calendar.getTime(), 2000);
/**
* 3、等待delay毫秒后执行且只执行一次task
* 如:现在是2020-04-06 12:12:15,delay=1000
* 那么会在2020-04-06 12:12:16 执行一次task--打印时间的任务
*/
// myTimerTask.setName("schedule 3 ========");
// timer.schedule(myTimerTask, 1000);
/**
* 4、等待delay毫秒首次执行task 和2类似
* 之后每隔period毫秒重复执行一次task
* 如:现在是2020-04-06 12:12:15,delay=1000 ms
* 那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
// myTimerTask.setName("schedule 4 ========");
// timer.schedule(myTimerTask,1000, 2000);
// ----------- scheduleAtFixedRate 的用法 -----------
/**
* 1、在时间等于或超过time的时候首次执行task 基本和schedule的用法 2一样
* 之后每隔period毫秒重复执行一次task
* 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
myTimerTask.setName("scheduleAtFixedRate 1 ========");
timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 2000);
实际效果:
实际操作一下试试看:
MyTimer.java
// ----------- schedule 的用法 -----------
/**
* 1、在时间等于或超过time的时候执行,且只执行一次task
* 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
*/
// myTimerTask.setName("schedule_1 ======== ");
// timer.schedule(myTimerTask, calendar.getTime());
/**
* 2、在时间等于或超过time的时候首次执行task
* 之后每隔period毫秒重复执行一次task
* 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
// myTimerTask.setName("schedule 2 ========");
// timer.schedule(myTimerTask, calendar.getTime(), 2000);
/**
* 3、等待delay毫秒后执行且只执行一次task
* 如:现在是2020-04-06 12:12:15,delay=1000
* 那么会在2020-04-06 12:12:16 执行一次task--打印时间的任务
*/
// myTimerTask.setName("schedule 3 ========");
// timer.schedule(myTimerTask, 1000);
/**
* 4、等待delay毫秒首次执行task 和2类似
* 之后每隔period毫秒重复执行一次task
* 如:现在是2020-04-06 12:12:15,delay=1000 ms
* 那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
// myTimerTask.setName("schedule 4 ========");
// timer.schedule(myTimerTask,1000, 2000);
// ----------- scheduleAtFixedRate 的用法 -----------
/**
* 1、在时间等于或超过time的时候首次执行task 基本和schedule的用法 2一样
* 之后每隔period毫秒重复执行一次task
* 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
// myTimerTask.setName("scheduleAtFixedRate 1 ========");
// timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 2000);
/**
* 2、等待delay毫秒首次执行task 基本和schedule的用法 4一样
* 之后每隔period毫秒重复执行一次task
* 如:现在是2020-04-06 12:12:15,delay=1000 ms
* 那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
myTimerTask.setName("scheduleAtFixedRate 2 ========");
timer.scheduleAtFixedRate(myTimerTask,1000, 2000);
实际效果:
以上两者的区别呢?
ScheduleAndScheduleAtFixedRateDifferenceTest.java
package com.java.study.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class ScheduleAndScheduleAtFixedRateDifferenceTest {
public static void main(String[] args) {
// 规定时间格式
final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 获取当前时间 具体到时分秒
Calendar calendar = Calendar.getInstance();
System.out.println("Current time is "
+ sf.format(calendar.getTime()));
// 把当前时间设置成6秒之前的时间
// 如:当前时间为 2020-04-07 12:00:06,
// 那么设置之后的时间为 2020-04-07 12:00:00
calendar.add(Calendar.SECOND, -6);
System.out.println("after -6s Current time is "
+ sf.format(calendar.getTime()));
Timer timer = new Timer();
// 第一次执行前是6秒前,之后每隔两秒执行一次
// 下面为了方便直接定义一个内部TimerTask类,然后简单写一些业务逻辑
// 1、看看schedule 的表现
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("schedule exec time is "
+ sf.format(scheduledExecutionTime()));
}
}, calendar.getTime(), 2000);
// 2、看看scheduleAtFixedRate 的表现
// todo
}
}
实际效果:
可以看到任务的执行不会因为当前时间被修改为6秒之前,就按照6秒之前的时间来执行,而是按照当前实际的时间来执行,然后每隔两秒执行一次。这就是schedule的特点。
ScheduleAndScheduleAtFixedRateDifferenceTest.java
package com.java.study.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class ScheduleAndScheduleAtFixedRateDifferenceTest {
public static void main(String[] args) {
// 规定时间格式
final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 获取当前时间 具体到时分秒
Calendar calendar = Calendar.getInstance();
System.out.println("Current time is "
+ sf.format(calendar.getTime()));
// 把当前时间设置成6秒之前的时间
// 如:当前时间为 2020-04-07 12:00:06,
// 那么设置之后的时间为 2020-04-07 12:00:00
calendar.add(Calendar.SECOND, -6);
System.out.println("after -6s Current time is "
+ sf.format(calendar.getTime()));
Timer timer = new Timer();
// 第一次执行前是6秒前,之后每隔两秒执行一次
// 下面为了方便直接定义一个内部TimerTask类,然后简单写一些业务逻辑
// 1、看看schedule 的表现
// timer.schedule(new TimerTask() {
// @Override
// public void run() {
// System.out.println("schedule exec time is "
// + sf.format(scheduledExecutionTime()));
// }
// }, calendar.getTime(), 2000);
// 2、看看scheduleAtFixedRate 的表现
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("schedule exec time is "
+ sf.format(scheduledExecutionTime()));
}
}, calendar.getTime(), 2000);
}
}
实际效果:
可以看到当前时间是52,但是计划执行时间是从6秒前开始算的,实际上下图红框中的4次schedule exec time是52秒这个时间点并发执行了3次(即“追赶”)才追上52这个时间点,之后才是真正的每隔2秒执行一次。
ScheduleAndScheduleAtFixedRateDifferenceTest2.java
package com.java.study.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class ScheduleAndScheduleAtFixedRateDifferenceTest2 {
public static void main(String[] args) {
// 规定时间格式
final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 获取当前时间 具体到时分秒
Calendar calendar = Calendar.getInstance();
System.out.println("Current time is "
+ sf.format(calendar.getTime()));
Timer timer = new Timer();
// 第一次执行当前时间,之后计划是每隔2秒执行一次,但是timertask任务每次实际执行时间是3秒,所以以后每次执行都是间隔3秒
// 下面为了方便直接定义一个内部TimerTask类,然后简单写一些业务逻辑
// 1、看看 schedule 的表现
timer.schedule(new TimerTask() {
@Override
public void run() {
// try 防止出现异常问题
try {
Thread.sleep(3000); // 这里强制让timertask任务执行时间3秒,超过设定的间隔时间2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印最近一次的计划时间
System.out.println("schedule exec time is "
+ sf.format(scheduledExecutionTime()));
}
}, calendar.getTime(), 2000);
// 2、看看 scheduleAtFixedRate 的表现
}
}
实际效果:
可以看到执行间隔是3秒,而不是2秒了。
ScheduleAndScheduleAtFixedRateDifferenceTest2.java
package com.java.study.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class ScheduleAndScheduleAtFixedRateDifferenceTest2 {
public static void main(String[] args) {
// 规定时间格式
final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 获取当前时间 具体到时分秒
Calendar calendar = Calendar.getInstance();
System.out.println("Current time is "
+ sf.format(calendar.getTime()));
Timer timer = new Timer();
// 第一次执行当前时间,之后计划是每隔2秒执行一次,但是timertask任务每次实际执行时间是3秒,所以以后每次执行都是间隔3秒
// 下面为了方便直接定义一个内部TimerTask类,然后简单写一些业务逻辑
// 1、看看 schedule 的表现
// timer.schedule(new TimerTask() {
// @Override
// public void run() {
// // try 防止出现异常问题
// try {
// Thread.sleep(3000); // 这里强制让timertask任务执行时间3秒,超过设定的间隔时间2秒
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// // 打印最近一次的计划时间
// System.out.println("schedule exec time is "
// + sf.format(scheduledExecutionTime()));
// }
// }, calendar.getTime(), 2000);
// 2、看看 scheduleAtFixedRate 的表现
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// try 防止出现异常问题
try {
Thread.sleep(3000); // 这里强制让timertask任务执行时间3秒,超过设定的间隔时间2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印最近一次的计划时间
System.out.println("schedule exec time is "
+ sf.format(scheduledExecutionTime()));
}
}, calendar.getTime(), 2000);
}
}
实际效果:
可以看到执行间隔还是2秒,而不是3秒。
4)其他重要函数
TimerTask的cancel()方法
实际操作一下试试看:
MyTimerTask.java
public class MyTimerTask extends TimerTask {
...
private Integer count = 0;
...
@Override
public void run() {
// 实现自己的业务逻辑 todo
if (count < 3) {
// 以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间
// 如:2020-04-06 12:12:12
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Current time is " + simpleDateFormat.format(calendar.getTime()));
// 此处是demo只增加一个打印输出语句
System.out.println("Current name is " + name);
count++;
} else {
cancel(); // 执行任务超过3次就取消task,相当于跳出定时任务循环
System.out.println("Cancel task done!");
}
}
...
实际效果:
TimerTask的scheduledExecutionTime()方法
实际操作一下试试看:
MyTimer.java
/**
* 2、等待delay毫秒首次执行task 基本和schedule的用法 4一样
* 之后每隔period毫秒重复执行一次task
* 如:现在是2020-04-06 12:12:15,delay=1000 ms
* 那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
* 之后每隔2秒(即2000ms)执行一次task
*/
// myTimerTask.setName("scheduleAtFixedRate 2 ========");
// timer.scheduleAtFixedRate(myTimerTask,1000, 2000);
// scheduledExecutionTime() 用法
// 最近发生此任务执行--安排的时间,为long型
myTimerTask.setName("scheduledExecutionTime 1111 ========");
timer.schedule(myTimerTask, 5000);
System.out.println("schedule time which task will run is " + simpleDateFormat.format(myTimerTask.scheduledExecutionTime()));
...
实际效果:
Timer的cancel()方法
实际操作一下试试看:
TimerCancelTest.java
package com.java.study.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
public class TimerCancelTest {
public static void main(String[] args) throws InterruptedException {
// 1. 创建一个Timer实例
Timer timer = new Timer();
// 2. 创建一个MyTimerTask实例
String inputname = "hello timer";
String inputname_1 = "hello timer 1";
MyTimerTask task1 = new MyTimerTask(inputname);
MyTimerTask task2 = new MyTimerTask(inputname_1);
// 获取当前时间
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Real Current time is " + simpleDateFormat.format(calendar.getTime()));
// task1首次执行时距离当前时间3秒执行,之后每隔2s执行一次;
// task2首次执行时距离当前时间1秒执行,之后每隔2s执行一次;
timer.schedule(task1, 3000, 2000);
timer.schedule(task2, 1000, 2000);
// 休眠5秒
Thread.sleep(5000);
// 获取当前的时间并打印
Date cancelTime = new Date();
System.out.println("cancel time is " + simpleDateFormat.format(cancelTime));
// 取消所有任务
timer.cancel();
System.out.println("All tasks be canceled!");
}
}
实际效果:
Timer的purge()方法
实际操作一下试试看:
TimerCancelAndPurgeTest.java
package com.java.study.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
public class TimerCancelAndPurgeTest {
public static void main(String[] args) throws InterruptedException {
// 1. 创建一个Timer实例
Timer timer = new Timer();
// 2. 创建一个MyTimerTask实例
String inputname = "hello timer";
String inputname_1 = "hello timer 1";
MyTimerTask task1 = new MyTimerTask(inputname);
MyTimerTask task2 = new MyTimerTask(inputname_1);
// 获取当前时间
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Real Current time is " + simpleDateFormat.format(calendar.getTime()));
// task1首次执行时距离当前时间3秒执行,之后每隔2s执行一次;
// task2首次执行时距离当前时间1秒执行,之后每隔2s执行一次;
timer.schedule(task1, 3000, 2000);
timer.schedule(task2, 1000, 2000);
System.out.println("current canceled tasks num is " + timer.purge());
// 休眠2秒
Thread.sleep(2000);
// 获取当前的时间并打印
Date cancelTime = new Date();
System.out.println("cancel time is " + simpleDateFormat.format(cancelTime));
// 取消task2任务
task2.cancel();
System.out.println("current canceled tasks num is " + timer.purge());
}
}
实际效果:
5)Timer的缺陷
以上Timer的缺陷,用Quartz就可以完美解决。
todo:
Quartz相关。。。