一.序言:
在JDK库汇总的Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务,Timer类的主要左右就是设置计划任务,但封装任务的类却是TimerTask类,执行计划任务的代码要放入TimerTask的子类中,因为TimerTask是一个抽象类.
二.demo演示:
1.指定未来的时间执行任务:
public class MyTask1 extends TimerTask{
@Override
public void run() {
try{
System.err.println("任务运行了! 时间为: "+new Date());
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("当前时间为: "+new Date());
Calendar instance = Calendar.getInstance();
//对当前时间进行延后10秒,目的是为了测试未来时间
instance.add(Calendar.SECOND,10);
//获取到未来10秒后的时间
Date time = instance.getTime();
Timer timer = new Timer();
MyTask1 myTask = new MyTask1();
timer.schedule(myTask,time);
}
}
运行结果:
2.计划时间早于当前时间,则立即执行task任务:
public class MyTask2 extends TimerTask{
@Override
public void run() {
System.err.println("执行了,时间为: "+new Date());
}
public static void main(String[] args) {
System.out.println("当前时间为: "+new Date());
Calendar instance = Calendar.getInstance();
instance.set(Calendar.SECOND,instance.get(Calendar.SECOND)-10);
Date time = instance.getTime();
System.out.println("计划时间为: "+time);
MyTask2 myTask2 = new MyTask2();
Timer timer = new Timer();
timer.schedule(myTask2,time);
}
}
运行结果:
3.多个延迟任务执行:
public class MyTask3 {
public static void main(String[] args) {
System.out.println("当前时间: "+new Date());
Date futureTime1 = MyTask3.getFutureTime(10);
System.out.println("计划时间: "+futureTime1);
Date futureTime2 = MyTask3.getFutureTime(15);
System.out.println("计划时间: "+futureTime2);
TimerTask taskA = new TimerTask() {
@Override
public void run() {
System.out.println("A执行了, 时间为:" + new Date());
}
};
TimerTask taskB = new TimerTask() {
@Override
public void run() {
System.out.println("B执行了, 时间为:" + new Date());
}
};
Timer timer = new Timer();
timer.schedule(taskA,futureTime1);
timer.schedule(taskB,futureTime2);
}
public static Date getFutureTime(int amount){
Calendar instance1 = Calendar.getInstance();
instance1.add(Calendar.SECOND,amount);
return instance1.getTime();
}
}
运行结果:
TimerTask是以队列的方式一个一个被顺序的执行,所以执行的时间有可能与预期的时间不一致,
因为前面的任务有可能消耗的时间较长,则后面的任务运行的时间也被延后.
4.在指定的时间内,有时间间隔的无限期的执行,如果计划时间早于当前时间则立即执行:
public class MyTask4 extends TimerTask{
@Override
public void run() {
System.out.println("执行了,时间为: "+new Date());
}
public static void main(String[] args) {
System.out.println("当前时间为: "+new Date());
Calendar instance = Calendar.getInstance();
//计划时间晚于当前时间10秒
// instance.add(Calendar.SECOND,10);
//计划时间早于当前时间10秒
instance.set(Calendar.SECOND,instance.get(Calendar.SECOND)-10);
Date time = instance.getTime();
MyTask4 task4 = new MyTask4();
Timer timer = new Timer();
timer.schedule(task4,time,4000);
}
}
运行结果:
三.Timer类的研究
1.构造方法
/**
* this调用的是第三个构造方法
*/
public Timer() {
this("Timer-" + serialNumber());
}
/**
* this调用的是第四个构造方法
* 传入true,表示需要守护进程
*/
public Timer(boolean isDaemon) {
this("Timer-" + serialNumber(), isDaemon);
}
public Timer(String name) {
thread.setName(name);
thread.start();
}
public Timer(String name, boolean isDaemon) {
thread.setName(name);
thread.setDaemon(isDaemon);
thread.start();
}
2.核心方法schedule
方法一:
/**
* task 待调度的任务
* delay 任务执行前的毫秒延迟
*/
public void schedule(TimerTask task, long delay) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
sched(task, System.currentTimeMillis()+delay, 0);
}
方法二:
/**
* task 待调度的任务
* time 执行任务的时间
*/
public void schedule(TimerTask task, Date time) {
sched(task, time.getTime(), 0);
}
方法三:
/**
* task 待调度的任务
* delay 任务执行前的毫秒延迟
* period 连续任务执行之间的时间(以毫秒为单位)
*/
public void schedule(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, -period);
}
方法四:
/**
* task 待调度的任务
* firstTime 第一次任务执行的时间
* period 连续任务执行之间的时间(以毫秒为单位)
*/
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
最后:
所有的sched()方法调用的都是以下这个方法:
private void sched(TimerTask task, long time, long period) {
if (time < 0)
throw new IllegalArgumentException("Illegal execution time.");
// Constrain value of period sufficiently to prevent numeric
// overflow while still being effectively infinitely large.
if (Math.abs(period) > (Long.MAX_VALUE >> 1))
period >>= 1;
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}
以上是个人的学习和理解,希望对大家学习有帮助。