定时任务的基本概念,Timer的函数,综合运用和缺陷
基于给定的时间点,给定的时间间隔或者给定的执行次数自动执行的任务。
Timer 和Quartz
Timer:
出身:由jdk提供,调用方式简单粗暴;
能力:Timer能完成一些简单的定时任务,如需要指定某个具体时间执行任务的话,Timer就能轻松实现。
Quartz
出身:需要引入架包
能力:能完成比较复杂的功能需求
底层机制:能够实现多个执行线程
定义:有且仅有一个后台线程对多个业务线程进行定时定频率的调度
Timer(后台执行线程)对TimerTask(业务线程)的定时调用
通过程序来讲解Timer,打开Eclipse
创建java工程MyTimerProject
创建包和class文件
MyTimerTask.java
package com.vishuo.timer;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask{
private String name;
public MyTimerTask(String inputName){
name=inputName;
}
@Override
public void run() {
// TODO Auto-generated method stub
//打印当前name的内容
System.out.println("Current exec name is:"+name);
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}
创建MyTimer类
package com.vishuo.timer;
import java.util.Timer;
public class MyTimer {
public static void main(String[] args) {
//1.创建一个timer实例
Timer timer = new Timer();
//2.创建一个MyTimerTask实例
MyTimerTask myTimerTask = new MyTimerTask("No.1");
//3.通过timer定时定频率调用myTimerTask的业务逻辑
//即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次
timer.schedule(myTimerTask, 2000L,1000L);
}
}
schedule的四种用法
schedule(task,time)
参数:task-所要安排的任务
time-执行任务的时间
作用:在时间等于或超过time的时候执行且仅执行一次task
schedule(task,time,period)
参数
task—所要安排的任务
time—首次执行任务的时间
period—执行一次task的时间间隔,单位是毫秒
作用
时间等于或超过time时首次执行task
之后每隔period毫秒重复执行一次task
schedule(task,delay)
参数
task—所要安排的任务
delay—执行任务前的延迟时间,单位是毫秒
作用:等待delay毫秒后执行且仅执行一次task
schedule(task,delay,period)
参数
task—所要安排的任务
delay—执行任务前的延迟时间,单位是毫秒
period—执行一次task的时间间隔,单位是毫秒
作用:等待delay毫秒后首次执行task
之后没隔period毫秒重复执行一次task
scheduleAtFixedRate(task,time,period)
参数
task—所要安排的任务
time—首次执行任务前的时间
period—执行一次task的时间间隔,单位是毫秒
作用:时间等于或超过time时首次执行task
之后每隔period毫秒重复执行一次task
scheduleAtFixedRate(task,delay,period)
参数
task—所要安排的任务
delay—执行任务前的延迟时间,单位是毫秒
period—执行一次task的时间间隔,单位是毫秒
作用:等待delay毫秒后首次执行task
之后没隔period毫秒重复执行一次task
全部方法代码示例:
MyTimerTask类
package com.vishuo.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask{
private String name;
public MyTimerTask(String inputName){
name=inputName;
}
@Override
public void run() {
// TODO Auto-generated method stub
//以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间
//如2016-11-11 00:00:00
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Curren exec time is:"+sf.format(calendar.getTime()));
//打印当前name的内容
System.out.println("Current exec name is:"+name);
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}
MyTimer类
package com.vishuo.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
public class MyTimer {
public static void main(String[] args) {
// 1.创建一个timer实例
Timer timer = new Timer();
// 2.创建一个MyTimerTask实例
MyTimerTask myTimerTask = new MyTimerTask("No.1");
// 3.通过timer定时定频率调用myTimerTask的业务逻辑
//即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次
// timer.schedule(myTimerTask, 2000L,1000L);
/*
* 获取当前时间,并设置成距离当前时间三秒之后的时间
* 如当前时间是2016-11-10 23:59:57
* 则设置后的时间则为2016-11-11 00:00:00
*/
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sf.format(calendar.getTime()));//获取当前时间
calendar.add(Calendar.SECOND, 3);//获取当前时间后三秒的时间
// ______schedule的用法______
/*
* 1.在时间等于或超过time的时候执行且仅执行一次task
* 如在2016-11-11 00:00:00执行一次task:打印任务的名字
*/
// myTimerTask.setName("schedule1");
// timer.schedule(myTimerTask, calendar.getTime());
/*
* 2.时间等于或超过time时首次执行task
* 之后每隔period毫秒重复执行一次task
* 如在2016-11-11 00:00:00第一次执行task:打印任务的名字
* 之后每隔两秒执行一次task
*/
// myTimerTask.setName("schedule2");
// timer.schedule(myTimerTask, calendar.getTime(),2000);
/*
* 3.等待delay毫秒后执行且仅执行一次task
* 如现在是2016-11-11 00:00:00
* 则在2016-11-11 00:00:00执行一次task:打印任务的名字
*/
// myTimerTask.setName("schedule3");
// timer.schedule(myTimerTask, 1000);
/*
* 4.等待delay毫秒后首次执行task
* 之后每隔period毫秒重复执行一次task
* 如现在是2016-11-11 00:00:00
* 则在2016-11-11 00:00:00第一次执行task:打印任务的名字
* 之后每隔两秒执行一次task
*/
// myTimerTask.setName("schedule4");
// timer.schedule(myTimerTask, 3000,2000);
// —————————— scheduleAtFixedRate的用法 ——————————
/*
* 1.时间等于或超过time时首次执行task
* 之后没隔period毫秒重复执行一次task
* 如在2016-11-11 00:00:00第一次执行task:打印任务名字
* 之后每隔两秒执行一次task
*/
// myTimerTask.setName("scheduleAtFixedRate1");
// timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 2000);
/*
* 2.等待delay毫秒首次执行task
* 之后没隔period毫秒重复执行一次task
* 如在2016-11-11 00:00:00
* 则在2016-11-11 00:00:01第一次执行task:打印任务名字
* 之后每隔两秒执行一次task
*/
myTimerTask.setName("scheduleAtFixedRate2");
timer.scheduleAtFixedRate(myTimerTask,3000, 2000);
}
}
作用:取消当前TimerTask里的任务
代码示例
修改MyTimerTask类,使程序执行三次后,结束任务。上面的MyTimer保持不变,依旧让其运行
myTimerTask.setName("scheduleAtFixedRate2");
timer.scheduleAtFixedRate(myTimerTask,3000, 2000);
MyTimerTask类修改如下:
package com.vishuo.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask{
private String name;
private Integer count = 0;
public MyTimerTask(String inputName){
name=inputName;
}
@Override
public void run() {
// TODO Auto-generated method stub
if(count < 3){
//以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间
//如2016-11-11 00:00:00
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Curren exec time is:"+sf.format(calendar.getTime()));
//打印当前name的内容
System.out.println("Current exec name is:"+name);
count ++;
}else{
cancel();
System.out.println("Task cancel!");
}
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}
作用:返回次任务最近实际执行的已安排执行的时间
返回值:最近发生此任务执行安排的时间,为long型
package com.vishuo.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
public class MyTimer {
public static void main(String[] args) {
// 1.创建一个timer实例
Timer timer = new Timer();
// 2.创建一个MyTimerTask实例
MyTimerTask myTimerTask = new MyTimerTask("No.1");
// 3.通过timer定时定频率调用myTimerTask的业务逻辑
//即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次
// timer.schedule(myTimerTask, 2000L,1000L);
/*
* 获取当前时间,并设置成距离当前时间三秒之后的时间
* 如当前时间是2016-11-10 23:59:57
* 则设置后的时间则为2016-11-11 00:00:00
*/
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sf.format(calendar.getTime()));//获取当前时间
calendar.add(Calendar.SECOND, 3);//获取当前时间后三秒的时间
/*
* scheduledExecutionTime代码示例
*/
myTimerTask.setName("schedule4");
timer.schedule(myTimerTask, 3000);
System.out.println("scheduled time is"+ sf.format(myTimerTask.scheduledExecutionTime()));
}
}
作用:终止此计时器,丢弃所有当前已安排的任务
代码示例:
新增CancelTest类
package com.vishuo.timer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
public class CancelTest {
public static void main(String[] args) throws InterruptedException {
// 创建Timer实例
Timer timer = new Timer();
// 创建TimerTask实例
MyTimerTask task1 = new MyTimerTask("task1");
MyTimerTask task2 = new MyTimerTask("task2");
//获取当前的执行时间并打印
Date startTime = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("start time is:"+sf.format(startTime));
//task1首次执行是距离现在时间3秒后执行,之后每隔2秒执行一次;
//task2首次执行是距离现在时间1秒后执行,之后每隔2秒执行一次;
timer.schedule(task1, 3000,2000);
timer.schedule(task2, 1000,2000);
//休眠5秒
Thread.sleep(5000);
//获取当前的执行时间并打印
Date cancelTime = new Date();
System.out.println("cancel time is :"+sf.format(cancelTime));
//取消所有任务
timer.cancel();
System.out.println("Tasks all canceled!");
}
}
作用:从此计时器的任务队列中移除所有已取消的任务
返回值:从队列中移除的任务数
演示代码:修改CancelTest类
package com.vishuo.timer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
public class CancelTest {
public static void main(String[] args) throws InterruptedException {
// 创建Timer实例
Timer timer = new Timer();
// 创建TimerTask实例
MyTimerTask task1 = new MyTimerTask("task1");
MyTimerTask task2 = new MyTimerTask("task2");
// 获取当前的执行时间并打印
Date startTime = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("start time is:" + sf.format(startTime));
// task1首次执行是距离现在时间3秒后执行,之后每隔2秒执行一次;
// task2首次执行是距离现在时间1秒后执行,之后每隔2秒执行一次;
timer.schedule(task1, 3000, 2000);
timer.schedule(task2, 1000, 2000);
System.out.println("current canceled task number is:"+timer.purge());
// 休眠5秒
// Thread.sleep(5000);
//休眠2秒
Thread.sleep(2000);
// 获取当前的执行时间并打印
Date cancelTime = new Date();
System.out.println("cancel time is :" + sf.format(cancelTime));
// 取消所有任务
// timer.cancel();
// System.out.println("Tasks all canceled!");
//取消task2
task2.cancel();
System.out.println("current canceled task number is:"+timer.purge());
}
}
两种情况看区别
1.首次计划执行的时间早于当前的时间
schedule方法:“fixed-delay”;如果第一次执行时间被delay了,随后的执行时间按照上一次实际执行完成的时间点进行计算。
示例代码:
新建DifferenceTest类
package com.vishuo.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class DifferenceTest {
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秒前的时间,若当前时间为2016-12-28 00:00:06
// 那么设置之后时间变成2016-12-28 00:00:00
calendar.add(Calendar.SECOND, -6);
Timer timer = new Timer();
// 第一次执行时间为6秒前,之后每隔两秒钟执行一次
timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
// 打印当前的计划执行时间
System.out.println("Scheduled exec time is :" + sf.format(scheduledExecutionTime()));
System.out.println("Task is being executed!");
}
}, calendar.getTime(), 2000);
}
}
scheduleAtFiexedRate方法
“fixed-rate”:如果第一次执行时间被delay了,随后的执行时间按照上一次开始的时间点进行计算,并且为了赶上进度会多次执行任务,因此TimerTask中的执行体需要考虑同步
代码示例:
修改DifferenceTest类
// 第一次执行时间为6秒前,之后每隔两秒钟执行一次
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
// 打印当前的计划执行时间
System.out.println("Scheduled exec time is :" + sf.format(scheduledExecutionTime()));
System.out.println("Task is being executed!");
}
}, calendar.getTime(), 2000);
2.任务执行所需时间超出任务的执行周期间隔
schedule方法
下一次执行时间相对于上一次实际执行完成的时间点,因此执行时间会不断延后
代码示例:
修改DifferenceTest类
package com.vishuo.timer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class DifferenceTest {
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秒前的时间,若当前时间为2016-12-28 00:00:06
// 那么设置之后时间变成2016-12-28 00:00:00
// calendar.add(Calendar.SECOND, -6);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
// 打印当前的计划执行时间
System.out.println("Scheduled exec time is :" + sf.format(scheduledExecutionTime()));
System.out.println("Task is being executed!");
}
}, calendar.getTime(), 2000);
}
}
scheduleAtFixedRate方法
下一次执行时间相对于上一次开始的时间点,因此执行时间一般不会延后,因此存在并发性
代码示例:修改DifferenceTest类
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
// 打印当前的计划执行时间
System.out.println("Scheduled exec time is :" + sf.format(scheduledExecutionTime()));
System.out.println("Task is being executed!");
}
}, calendar.getTime(), 2000);