Java的TimerTask中的任务执行时长比定时器的运行时间间隔更长时的解决办法

晚风。

任务执行时长比定时器的运行时间间隔更长,那么定时器的执行时间间隔将被拉长至任务执行的时长。比如,定时器定好2秒执行一次,但是任务执行需要花费3秒,那么实际上定时器是每3秒执行一次的。

定时器及main方法:


public static void main(String[] args) throws Exception {

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

System.out.println("Time:" + format.format(new java.util.Date()));

System.out.println("Timer will start after 3 s.");

Timer timer = new Timer(); //统计定时器

timer.schedule(new TimerTask() {

@Override

public void run() {

new Test().printDate();

}

}, 0, 2000);

}


printDate方法:


public void printDate() {

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new java.util.Date()));

}


此时输出:


Time:2019-06-10 15:51:23.889

Timer will start after 3 s.

2019-06-10 15:51:26.893

2019-06-10 15:51:29.893

2019-06-10 15:51:32.893

2019-06-10 15:51:35.893

2019-06-10 15:51:38.893


Process finished with exit code 1

可以看到,任务实际上是每3秒执行一次的,这跟我们的预期是不相符的。


解决办法,在定时器任务的run方法中新建一个线程,让实际执行的任务在新线程中执行。此时,定时器任务的实际任务就是创建线程然后运行,线程运行后,任务就算结束了。耗时任务花费的时间算新线程的,跟定时器就没有关系了,这就规避了任务执行时长过长的问题。


修改后就变成:


timer.schedule(new TimerTask() {

@Override

public void run() {

new Thread(new Runnable() {

@Override

public void run() {

new Test().printDate();

}

}).start();

}

}, 0, 2000);

输出:


Time:2019-06-10 16:02:23.732

Timer will start after 3 s.

2019-06-10 16:02:26.738

2019-06-10 16:02:28.741

2019-06-10 16:02:30.743

2019-06-10 16:02:32.742

2019-06-10 16:02:34.742

2019-06-10 16:02:36.742

2019-06-10 16:02:38.742


Process finished with exit code 1

主 楼 发布于:2019-06-10 16:03:58回复

发表回复: