任务调度(一)——jdk自带的Timer

       说到任务调度,你们可能会想到Quartz框架,可是jdk自带的简单任务调度工具类,反而了解的人并非不少。我以为若是你的业务相对简单的话,不必非得用Quartz等框架,使用Timer彻底能够胜任的。简单来分享一下我了解的Timer。java


  Timer是jdk中提供的一个定时器工具,使用的时候会在主线程以外起一个单独的线程执行指定的计划任务,能够指定执行一次或者反复执行屡次。框架

  TimerTask是一个实现了Runnable接口的抽象类,表明一个能够被Timer执行的任务。ide


       我是用TimerTask来建立一个任务,其中run方法里是任务调度的逻辑。使用一个Timer对象来调度任务。工具


       首先给一个特别简单的示例:测试

package com.tgb.ccl.schema;

import java.util.Date;
import java.util.TimerTask;

/** 
 * 不可动态修改的任务
 * 
 * @author arron
 * @date 2015年5月7日 下午1:52:15 
 * @version 1.0 
 */
public class FixedTimerTask extends TimerTask{

	@Override
	public void run() {
		Date d = new Date();
		for(int i=0;i<3;i++){
			try {
				Thread.sleep(1000);
				System.out.println("已执行【"+(i+1)+"】秒钟,at: "+d.toLocaleString());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("本次任务调度结束,at: "+new Date().toLocaleString());
		System.out.println("---------------------------");
	}
	
}

package com.tgb.ccl.schema;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;

/**
 * 任务调度管理器
 * 
 * @author arron
 * @date 2015年5月7日 下午1:57:19
 * @version 1.0
 */
public class TaskManager {
//	private static final long PERIOD = 5 * 60 * 1000;// 5分钟
	private static final long PERIOD = 5 * 1000;// 1秒钟

	public TaskManager() {
		Timer timer = new Timer();
		FixedTimerTask task = new FixedTimerTask();
		System.out.println("start");
		
		
		//0表示当即执行一次,之后每隔一段时间执行一次
		timer.schedule(task, 0, PERIOD);
		
		//1000表示1秒后执行一次,之后每隔一段时间执行一次
		//timer.schedule(task, 1000, PERIOD);
		
		//0表示当即执行一次,之后每隔一段时间执行一次
		//timer.schedule(task, 1000, PERIOD);
		
		// 在当天14点4分整,执行一次,之后再也不执行
		//timer.schedule(task, bookTime(15,0,0));
		
		//在当天14点4分整,执行一次,之后每隔一段时间执行一次
		//若是时间超过了设定时间,会当即执行一次
//		timer.schedule(task, bookTime(0,34,10),PERIOD);
//		timer.scheduleAtFixedRate(task, bookTime(0,40,0),PERIOD);

	}
	

	private Date bookTime(int hour, int minute, int second) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.HOUR_OF_DAY, hour);
		calendar.set(Calendar.MINUTE, minute);
		calendar.set(Calendar.SECOND, second);
		Date date = calendar.getTime();
		return date;
	}
	
	public static void main(String[] args) {
		 new TaskManager();
	}
}

       只要执行main方法就能够测试了。
spa


       你们可能已经注意到了,timer的schedule方法是重载的。参数主要有必须有一个TimerTask实例。第二个参数若是是long类型的,这个参数则是表示延迟时间,以毫秒为单位。若是为1000,那就是1秒后执行任务调度。若是是Date类型,则表示设定任务开始执行的时刻。当时间到达这个时刻,那么任务会自动开始调度。固然若是当前时间已经超过了设定的开始时间,那么会当即执行一次。第三个参数则是可选参数,是long类型的参数,表示调度的间隔时间。若是有这个参数,表示任务是重复性的调度。不然只会执行一次。这个参数依旧以毫秒为单位。线程


       若是你稍微注意一下,就会发现timer不仅提供了schedule方法,还提供了scheduleAtFixedRate方法。这两个方法都是任务调度方法,他们有什么区别呢?code


       区别在于当当前时间已经超过了设定执行时间,schedule方法会当即执行,第二次执行则是按当前执行时间+间隔时间来算的(固然任务执行时间超过了间隔时间,则在第一次执行完毕后,立马会执行第二次)。而scheduleAtFixedRate方法,一样是当即执行一次,可是它第二次执行则是按照(当前执行时间-设定的时间)/时间间隔来计算从设定时间到如今还须要执行多少次。
对象


       举个例子:任务调度须要执行2s,间隔时间是10s,我设定的是8点执行。当前时间为8点0分10秒,若是是schedule方法,则会当即执行一次,第二次执行时间则是08:00:20。若是是scheduleAtFixedRate方法,则会当即执行一次,而后计算08:00:10-08:00:00整好还能够执行一次,因此会在08:00:12时,会当即再执行一次,第三次执行则是在08:00:20时执行,之后每隔10s执行一次。接口

   

(左图是schedule方法的测试效果,右图是scheduleAtFixedRate方法的测试效果)

       这个跟网上不少人说的不太同样。不过这个是我测试出来了。他们说的那种结果反正我是测不出来。具体你相信哪一种,你本身试过就清楚了。


       下篇分享一下怎样动态修改Timer的调度计划,敬请期待。

相关文章
相关标签/搜索