java中定时任务各方式对比
@Scheduled
示例:
@Component
public class SpringScheduled {
@Scheduled(initialDelay = 2000,fixedDelay = 5000)
public void doSomething() {
System.out.println("=======================");
}
Timer
使用 Timer 实现任务调度的核心类是 Timer 和 TimerTask。其中 Timer 负责设定 TimerTask 的起始与间隔执行时间。使用者只需要创建一个 TimerTask 的继承类,实现自己的 run 方法,然后将其丢给 Timer 去执行即可。
Timer 的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。
示例:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("Time's up!");
}
},3*1000,1000);
ScheduledThreadPool-线程池
鉴于 Timer 的上述缺陷,Java 5 推出了基于线程池设计的 ScheduledExecutor。其设计思想是,每一个被调度的任务都会由线程池中一个线程去执行,通过new ScheduledThreadPoolExecutor(线程数)指定线程数,因此任务是并发执行的,相互之间不会受到干扰。需要注意的是,只有当任务的执行时间到来时,ScheduedExecutor 才会真正启动一个线程,其余时间 ScheduledExecutor 都是在轮询任务的状态。
示例:
ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1);
scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(true);
scheduler.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
scheduler.setRemoveOnCancelPolicy(true);
scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(System.currentTimeMillis()+"<><>"+System.nanoTime());
}
}, 1000, 2000, TimeUnit.MILLISECONDS);
ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1);
scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(true);
scheduler.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
scheduler.setRemoveOnCancelPolicy(true);
scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(System.currentTimeMillis()+"<><>"+System.nanoTime());
}
}, 1000, 2000, TimeUnit.MILLISECONDS);
ScheduledThreadPool中主要的两个接口
-
ScheduleAtFixedRate 每次执行时间为上一次任务开始起向后推一个时间间隔,即每次执行时间为 :initialDelay, initialDelay+period, initialDelay+2*period, …
-
ScheduleWithFixedDelay 每次执行时间为上一次任务结束起向后推一个时间间隔,即每次执行时间为:initialDelay, initialDelay+executeTime+delay, initialDelay+2executeTime+2delay。由此可见,ScheduleAtFixedRate 是基于固定时间间隔进行任务调度,ScheduleWithFixedDelay 取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度。