作者:京东保险 孙昊宇
引子:“指日可待”
让我们先从一个成语开始,“指日可待”。没错,我说的就是定时任务😏。
“指日可待”: 为任务指定好日程,就可以安心等待任务执行。
在实际场景中,我们往往需要在特定时间做某件事情,或以某个时间间隔重复某件事情,如定期备份数据、定时取消超时订单等。所有和时间有关的事情,都需要借助定时任务来完成。
定时任务可分为两种:本地定时任务、 分布式定时任务。
本地定时任务,即单机定时任务,适合做那些需要每台机器都执行的任务,如刷新每台机器的本地缓存;分布式定时任务则以一个分布式集群为单位执行任务,适用于支持在分布式场景下任务的高可用。
今天让我们看看Java中的本地定时任务,本文将介绍如何使用Timer、ScheduledExecutorService和@Scheduled三种方式实现本地定时任务。
读完本文,你会发现:原来每月最后一个工作日发工资,也可以用定时任务实现!
一、Timer
Timer,即java.util.Timer,是来自Java 1.3的古老定时器。
要使用Timer,要先创建一个TimerTask,作为Timer要执行的任务:
// 创建Timer对象
Timer timer = new Timer();
// 创建TimerTask:task1
TimerTask task1 = new TimerTask() {@Overridepublic void run() {System.out.println("task1开始执行:" + new Date().getSeconds());}
};
有了Timer和TimerTask,就可以安排任务执行。让我们简单了解下Timer的用法:
(1)单次执行
使用Timer.schedule方法,只需传入TimerTask和延迟时间,即可让任务在指定的延迟时间后执行一次。也可以传入Date,让任务在指定的时刻执行:
// 5s后执行
timer.schedule(task1, 5000);
// 指定时刻。如果传入当前时刻,立即执行
timer.schedule(task1, new Date());
如果直接运行以上代码,会出现“Task already scheduled or cancelled”异常。这是因为一个TimerTask只能被schedule方法调度一次。如果需要执行两个任务,我们需要创建两个TimerTask。我们让两个任务在执行时分别打印当前时刻的秒数,全部代码如下:
// 创建Timer对象
Timer timer = new Timer();
// 创建TimerTask:task1
TimerTask task1 = new TimerTask() {@Overridepublic void run() {System.out.println("task1开始执行:" + new Date().getSeconds());}
};
// 创建TimerTask:task2
TimerTask task2 = new TimerTask() {@Overridepublic void run() {System.out.println("task2开始执行:" + new Date().getSeconds());}
};
// 5s后执行
timer.