公司做项目,其中涉及到一个游戏的业务逻辑,需要使用定时类去执行,在使用Timer的时候,发现总是出现奇怪的问题。
如下代码:
package com.yifeng.test22;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class RunLoter {
private static Timer timer = new Timer();
static public class Mytest1 extends TimerTask {
@Override
public void run() {
// 这里不干别的只是睡觉
try {
System.out.println("Mytest1运行了,当前时间为" + new Date());
Thread.sleep(20000);
System.out.println("Mytest2运行了,当前时间为" + new Date());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static public class Mytest2 extends TimerTask {
@Override
public void run() {
System.out.println("Mytest2运行了,当前时间为" + new Date());
}
}
public static void main(String[] args) throws ParseException {
Mytest1 mytest1=new Mytest1();
Mytest2 mytest2=new Mytest2();
timer.schedule(mytest1, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-11-11 09:49:40"));
timer.schedule(mytest2, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-11-11 09:49:40"));
}
}
我去,Test2 竟然没按照时间执行,而是在test1执行结束后才去执行的。
究其原因:
这是因为Timer基本处理模型是单线程调度的任务队列模型,Timer不停地接受调度任务,所有任务接受Timer调度后加入TaskQueue,TimerThread不停地去TaskQueue中取任务来执行.此种方式的不足之处为当某个任务执行时间较长,以致于超过了TaskQueue中下一个任务开始执行的时间,会影响整个任务执行的实时性。
你可以试用scheduleAtFixedRate方法,它会让任务尽量保证在规定的时间频率执行,如:定的时间频率是2s,因为系统繁忙,之后的2.5秒后任务才得以执行第二次,然后,Timer记下了这个延迟,并尝试在下一个任务的时候弥补这个延迟,那么,1.5秒后,任务将执行.