笔者这篇博文主要写的是Timer和ScheduledExecutorService完成定时任务调度的区别。
1)因为Timer是单线程执行的,如果第一个任务执行用掉了过多的时间,会导致第二个任务不能在指定延迟时间后得到调用。
我们来写一个demo
package org.hl.javaapi.scheduledapi;
import java.util.Timer;
import java.util.TimerTask;
public class MyTimerTest {
public static void main(String[] args) {
final long startTime = System.currentTimeMillis();
Timer timer = new Timer();
TimerTask timerTask1 = new TimerTask() {
@Override
public void run() {
System.out.println("在这么多毫秒后,得到执行:" + (System.currentTimeMillis() - startTime));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
TimerTask timerTask2 = new TimerTask() {
@Override
public void run() {
System.out.println("在这么多毫秒后,得到执行:" + (System.currentTimeMillis() - startTime));
}
};
//1秒后得到执行
timer.schedule(timerTask1, 1000);
//3秒后得到执行
timer.schedule(timerTask2, 3000);
}
}
输出的结果为:
在这么多毫秒后,得到执行:1001
在这么多毫秒后,得到执行:6002
Process finished with exit code 1
上代码
package org.hl.javaapi.scheduledapi;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MyScheduledExecutorServiceTest {
private static long startTime;
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
TimerTask timerTask1 = new TimerTask() {
@Override
public void run() {
System.out.println("task1 invoked in " + (System.currentTimeMillis() - startTime));
try {
//人为睡眠5秒
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
TimerTask timerTask2 = new TimerTask() {
@Override
public void run() {
System.out.println("task2 invoked in "
+ (System.currentTimeMillis() - startTime));
}
};
startTime = System.currentTimeMillis();
scheduledExecutorService.schedule(timerTask1, 1000, TimeUnit.MILLISECONDS);
scheduledExecutorService.schedule(timerTask2, 3000, TimeUnit.MILLISECONDS);
}
}
task1 invoked in 1000
task2 invoked in 3001
Process finished with exit code 1
这样符合我们的要求,因为ScheduledExecutorService内部是个线程池。有多个线程,所以就算第一个任务占用了较多的时间,第二个任务也会在指定的时间执行。
2)当Timer的第一个任务抛出了异常,第二个任务也就不执行了。而ScheduledExecutorService第二个任务还可以接着去执行。
package org.hl.javaapi.scheduledapi;
import java.util.Timer;
import java.util.TimerTask;
public class MyTimerTest1 {
private static long startTime;
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask timerTask1 = new TimerTask() {
@Override
public void run() {
throw new RuntimeException("人为的抛出异常");
}
};
TimerTask timerTask2 = new TimerTask() {
@Override
public void run() {
System.out.println("task2 get invoked in" + (System.currentTimeMillis() - startTime));
}
};
startTime = System.currentTimeMillis();
timer.schedule(timerTask1,1000);
timer.scheduleAtFixedRate(timerTask2,3000,1000);
}
}
Exception in thread "Timer-0" java.lang.RuntimeException: 人为的抛出异常
at org.hl.javaapi.scheduledapi.MyTimerTest1$1.run(MyTimerTest1.java:15)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Process finished with exit code 0
接下来我们看一看ScheduledExecutorService的实现
package org.hl.javaapi.scheduledapi;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MyScheduledExecutorServiceTest1 {
private static long startTime;
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
TimerTask timerTask1 = new TimerTask() {
@Override
public void run() {
throw new RuntimeException("人为地抛出异常");
}
};
TimerTask timerTask2 = new TimerTask() {
@Override
public void run() {
System.out.println("task get invoked in :" + (System.currentTimeMillis() - startTime));
}
};
startTime = System.currentTimeMillis();
scheduledExecutorService.schedule(timerTask1, 1000, TimeUnit.MILLISECONDS);
scheduledExecutorService.scheduleAtFixedRate(timerTask2, 3000, 1000, TimeUnit.MILLISECONDS);
}
}
运行结果如下:
task get invoked in :3003
task get invoked in :4002
task get invoked in :5002
task get invoked in :6003
Process finished with exit code 1
3)
Timer执行周期任务时依赖系统时间