公司做项目,其中涉及到一个游戏的业务逻辑,需要使用定时类去执行,在使用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秒后,任务将执行.