几乎在所有的项目中,定时任务的使用都是不可或缺的,如果使用不当甚至会造成资损。还记得多年前在做金融系统时,出款业务是通过定时任务对外打款,当时由于银行接口处理能力有限,外加定时任务使用不当,导致发出大量重复出款请求。还好在后面环节将交易卡在了系统内部,未发生资损。
所以,系统的学习一下定时任务,是非常有必要的。这篇文章就带大家整体梳理学习一下Java领域中常见的几种定时任务实现。
线程等待实现
先从最原始最简单的方式来讲解。可以先创建一个thread,然后让它在while循环里一直运行着,通过sleep方法来达到定时任务的效果。
public class Task {
public static void main(String[] args) {
// run in a second
final long timeInterval = 1000;
Runnable runnable = new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("Hello !!");
try {
Thread.sleep(timeInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
这种方式简单直接,但是能够实现的功能有限,而且需要自己来实现。
JDK自带Timer实现
目前来看,JDK自带的Timer API算是最古老的定时任务实现方式了。Timer是一种定时器工具,用来在一个后台线程计划执行指定任务。它可以安排任务“执行一次”或者定期“执行多次”。
在实际的开发当中,经常需要一些周期性的操作,比如每5分钟执行某一操作等。对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。
核心方法
Timer类的核心方法如下:
// 在指定延迟时间后执行指定的任务
schedule(TimerTask task,long delay);
// 在指定时间执行指定的任务。(只执行一次)
schedule(TimerTask task, Date time);
// 延迟指定时间(delay)之后,开始以指定的间隔(period)重复执行指定的任务
schedule(TimerTask task,long delay,long period);
// 在指定的时间开始按照指定的间隔(period)重复执行指定的任务
schedule(TimerTask task, Date firstTime , long period);
// 在指定的时间开始进行重复的固定速率执行任务
scheduleAtFixedRate(TimerTask task,Date firstTime,long period);
// 在指定的延迟后开始进行重复的固定速率执行任务
scheduleAtFixedRate(TimerTask task,long delay,long period);
// 终止此计时器,丢弃所有当前已安排的任务。
cancal();
// 从此计时器的任务队列中移除所有已取消的任务。
purge();
使用示例
下面用几个示例演示一下核心方法的使用。首先定义一个通用的TimerTask类,用于定义用执行的任务。
public class DoSomethingTimerTask extends TimerTask {
private String taskName;
public DoSomethingTimerTask(String taskName) {
this.taskName = taskName;
}
@Override
public void run() {
System.out.println(new Date() + "