说明
本博客每周五更新一次。 定时任务是项目开发中常用功能,java web中常用spring boot schedule、Quartz、spring task等,本文围绕jdk自带定时任务类Timer。 Timer 是jdk自带定时器工具类,可配置执行一次或循环执行任务,默认单线程模式启动,如果当先任务异常,后续任务将不会执行,这是个坑,日常开发注意规避。
分享
一般实现
创建任务类
- 创建继承
TimerTask 的任务类,实现run 方法内需要执行的功能。实例如下:
public class DemoTimerTask extends TimerTask{
@Override
public void run() {
System.out.println("定时任务")
}
}
启动任务
- 任务执行方式有两种:执行一次和多次循环执行
- 执行一次:
new Timer().schedule(new DemoTimerTask(), new Date());
new Timer().schedule(new DemoTimerTask(), 1000);
new Timer().schedule(new DemoTimerTask(), new Date(),5000);
new Timer().schedule(new DemoTimerTask(), 1000,5000);
new Timer().scheduleAtFixedRate(new DemoTimerTask(), new Date(),5000);
new Timer().scheduleAtFixedRate(new DemoTimerTask(), 1000,5000);
优化实现
timer缺陷
- timer任务执行时间并不准确,存在时间漂移情况,windows系统每个任务相差几到十几毫秒不等,linux没执行几个任务相差1毫秒,原因猜想是timer是单线程实现,执行时间受上个任务执行时长影响。
- timer当前任务失败,后续任务停止执行
- 当前任务执行时长大于等待时长,后续任务将阻塞影响业务计算。
ScheduledThreadPoolExecutor
代码实例
public class DemoTimerTask implements Runnable {
@Override
public void run() {
System.out.println("定时任务")
}
}
ScheduledThreadPoolExecutor stp=new ScheduledThreadPoolExecutor(5);
DemoTimerTask task=new DemoTimerTask();
stp.scheduleAtFixedRate(task, 2, 1, TimeUnit.SECONDS);
总结
- 一般java定时任务使用上面的技术足够,执行时间不苛刻直接使用timer,但注意任务内异常捕获,任务较多且有一定时间要求,使用
ScheduledThreadPoolExecutor ,多线程效率和时间精确度上更高。 - 如果高并发编程使用
ScheduledExecutorService ,可控性和效率更好。
|