基于给定时间点,给定时间间隔或者给定执行次数自动执行的任务
Timer | Quartz |
---|---|
由jdk提供 | openSymphony开源组织提供,依赖其他jar包 |
实现具体时间的定时任务 | 能实现一定频率的具体时间定时任务,功能更强大如实现每周早8点发消息 |
只有一个后台线程去执行任务 | 拥有线程池可调度多个线程执行任务 |
注:能用timer解决的定时任务尽量不要用quartz
timer
schedule(task,time):在时间等于或超过time的时候执行且仅执行一次task
scheduleschedulle(task,time,period):时间等于或超过time时首次执行task,之后每隔period毫秒重复执行一次task
schedule(task,delay):等待delay毫秒后执行且仅执行一次task
schedule(task,delay,period):等待delay毫秒后首次执行task,之后每隔period毫秒重复执行一次task
scheduleAtFixedRate(task,time,period):时间等于或超过time时首次执行task之后每隔period毫秒重复执行一次task
scheduleAtFixedRate(task,delay,period):等待delay毫秒首次执行task之后每隔period毫秒重复执行一次task
cancel()取消当前TimerTasker里的任务
scheduledExecutionTime():返回此任务最近实际执行的已安排执行的时间
cancel()终止此计时器,丢弃当前已安排的任务
purge()从此计时器的任务队列中移除所有已取消的任务
返回值是队列中移除的任务数
区别体现在两方面
1首次计划执行的时间早于当前时间
2任务执行所需时间超出任务的执行周期间隔
schedule | scheduleAtFixedRate |
---|---|
如果第一次执行时间被delay,随后的执行时间按照上一次实际执行完成的时间点计算而不会按照目前时间之前的时间执行 | 如果第一次执行时间被delay,随后的执行时间按照上一次开始的时间点进行计算,并且为了赶上进度会多次执行任务,因此TimerTask中的执行体需要考虑同步 |
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() {
// 打印当前的计划执行时间
System.out.println("Scheduled exec time is" + sf.format(scheduledExecutionTime()));
System.out.println("Task is being execued!");
}
}, calendar.getTime(), 2000L);
}
console:
Current time is :2018-02-25 17:56:07
Scheduled exec time is2018-02-25 17:56:07
Task is being execued!
Scheduled exec time is2018-02-25 17:56:09
Task is being execued!
Scheduled exec time is2018-02-25 17:56:11
Task is being execued!
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.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// 打印当前的计划执行时间
System.out.println("Scheduled exec time is" + sf.format(scheduledExecutionTime()));
System.out.println("Task is being execued!");
}
}, calendar.getTime(), 2000L);
}
console:
Current time is :2018-02-25 18:05:20
Scheduled exec time is2018-02-25 18:05:14
Task is being execued!
Scheduled exec time is2018-02-25 18:05:16
Task is being execued!
Scheduled exec time is2018-02-25 18:05:18
Task is being execued!
Scheduled exec time is2018-02-25 18:05:20
Task is being execued!
Scheduled exec time is2018-02-25 18:05:22
Task is being execued!
schedule | scheduleAtFixedRate |
---|---|
下一次执行时间相对于上一次实际执行完成的时间点晚,执行时间不断延后 | 下一次执行时间相对于上一次实际执行完成的时间点晚,执行时间不会延后,因此存在并发性 |
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();
// 第一次执行,之后每隔两秒执行一次
timer.schedule(new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
//打印最近一次的计划执行时间
System.out.println("scheduled exec time is:" + sf.format(scheduledExecutionTime()));
System.out.println("Task executes!");
}
}, calendar.getTime(), 2000L);
}
console:
Current time is :2018-02-25 19:08:00
scheduled exec time is:2018-02-25 19:08:00
Task executes!
scheduled exec time is:2018-02-25 19:08:03
Task executes!
scheduled exec time is:2018-02-25 19:08:06
Task executes!
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.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
//打印最近一次的计划执行时间
System.out.println("scheduled exec time is:" + sf.format(scheduledExecutionTime()));
System.out.println("Task executes!");
// 打印当前的计划执行时间
//System.out.println("Scheduled exec time is" + sf.format(scheduledExecutionTime()));
//System.out.println("Task is being execued!");
}
}, calendar.getTime(), 2000L);
}
console:
Current time is :2018-02-25 19:14:25
scheduled exec time is:2018-02-25 19:14:25
Task executes!
scheduled exec time is:2018-02-25 19:14:27
Task executes!
scheduled exec time is:2018-02-25 19:14:29
Task executes!
管理并发任务的缺陷:
Timer有且仅有一个线程去执行定时任务,如果存在多个任务,且任务时间过长,会导致执行效果与预期不符
当任务抛出异常的缺陷
如果TimerTask抛出RunTimeException,Timer会停止所有任务的执行
1、 对时效性要求的多任务并发作业
2、对复杂任务的调度
总结自慕课网Java定时任务调度工具详解