定时任务就是在指定时间执行程序,或周期性执行计划任务。Java中实现定时任务的方法有很多,本文从从JDK自带的一些方法来实现定时任务的需求。
Timer和TimerTask
本文先介绍Java最原始的解决方案:Timer和TimerTask
Timer和TimerTask可以作为线程实现的第三种方式,在JDK1.3的时候推出。但是自从JDK1.5之后不再推荐时间,而是使用ScheduledThreadPoolExecutor代替
public class Timer {} // TimerTask 是个抽象类 public abstract class TimerTask implements Runnable {}
快速入门
Timer运行在后台,可以执行任务一次,或定期执行任务。TimerTask类继承了Runnable接口,因此具备多线程的能力。一个Timer可以调度任意多个TimerTask,所有任务都存储在一个队列中顺序执行,如果需要多个TimerTask并发执行,则需要创建两个多个Timer。
很显然,一个Timer定时器,是单线程的
public static void main(String[] args) throws ParseException { Timer timer = new Timer(); //1、设定两秒后执行任务 //timer.scheduleAtFixedRate(new MyTimerTask1(), 2000,1000); //2、设定任务在执行时间执行,本例设定时间13:57:00 SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); Date time = dateFormatter.parse("2018/11/04 18:40:00"); //让在指定的时刻执行(如果是过去时间会立马执行 如果是将来时间 那就等吧) timer.schedule(new MyTimerTask1(), time); } //被执行的任务必须继承TimerTask,并且实现run方法 static class MyTimerTask1 extends TimerTask { public void run() { System.out.println("爆炸!!!"); } }
相关API简单介绍(毕竟已经不重要了):
schedule(TimerTask task, long delay, long period) --指定任务执行延迟时间
schedule(TimerTask task, Date time, long period) --指定任务执行时刻
scheduleAtFixedRate(TimerTask task, long delay, long period)
scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
这里需要注意区别:
schedule:
scheduleAtFixedRate:
相关文章度娘一下,可找到答案。因此本文不做介绍了,毕竟不是本文重点。
终止Timer线程
调用Timer.cancle()方法。可以在程序任何地方调用,甚至在TimerTask中的run方法中调用;
设置Timer对象为null,其会自动终止;
用System.exit方法,整个程序终止。
下面例子:
启动一个timer任务,执行指定次数/时间后停止任务
备注:该示例在某些特殊的场景会很有用的,比如守护监控、守护检查等等
/** * 定时器 * * @author fangshixiang * @description // * @date 2019/1/22 17:55 */ public class TaskTest { /** * 需求描述:满足条件后启动一个定时任务,再满足另外一个条件后停止此定时任务 * (阶段性定时任务) * 备注:若单线程就能搞定,就使用timer即可,若需要多线程环境,请使用JDK5提供的ScheduledThreadPoolExecutor */ public static void main(String[] args) { Timer timer = new Timer(); // 三秒后开始执行任务,每隔2秒执行一次 当执行的总次数达到10此时,停止执行 timer.schedule(new Task(timer, 10), 3 * 1000, 2000); } } class Task extends TimerTask { private Timer timer; private int exeCount; //此处没有线程安全问题 public Task(Timer timer, int exeCount) { this.timer = timer; this.exeCount = exeCount; } private int i = 1; @Override public void run() { System.out.println("第" + i++ + "次执行任务"); //处理业务逻辑start... //处理业务逻辑end... //若满足此条件 退出此线程 if (i > exeCount) { this.timer.cancel(); System.out.println("#### timer任务程序结束 ####"); } } }
输出:
第1次执行任务 第2次执行任务 第3次执行任务 第4次执行任务 第5次执行任务 第6次执行任务 第7次执行任务 第8次执行任务 第9次执行任务 第10次执行任务 #### timer任务程序结束 ####