Java定时任务以及ScheduledThreadPoolExecutor需要注意的问题

时间:2020-12-24 07:53:24

 Java提供Timer和ScheduledThreadPoolExecutor两个类实现定时任务,其中Timer简单易用,但所有任务都是由同一个线程来调度,任务串行执行,任务之间存在互相干扰,一是前一个任务的延迟会导致后面的任务延迟,二是前一个任务异常导致后面的任务不再执行,三是Timer执行周期任务时依赖系统时间,如果当前系统时间发生变化,执行行为也会出现变化。


   鉴于Timer的缺陷,Java 5提供了ScheduledThreadPoolExecutor实现定时任务,每个任务由线程池中一个线程去执行,任务并发执行,且相互之间不会受到干扰。此外,ScheduledExecutorService是基于时间延迟,不会由于系统时间的改变发生执行变化。但ScheduledThreadPoolExecutor要在某个时间点开始执行任务没有Timer方便,需要先计算出和执行时间点的时间差,然后设置第一次启动的延时。


   综上,对于复杂的调度,最好是使用开源软件,如Quartz。java培训机构排名对于普通的周期性任务,使用ScheduledThreadPoolExecutor就可以满足要求,但使用ScheduledThreadPoolExecutor时,必须注意两点:

   1. 一定要使用try{}catch(Throwable t){}捕获所有可能的异常,因为ScheduledThreadPoolExecutor会在任务执行遇到异常时取消后续执行。

   2. 注意scheduleAtFixedRate与scheduleWithFixedDelay的区别,scheduleAtFixedRate是上一个任务开始执行之后延迟设定时间再执行,是从上一个任务开始时计时,但对于运行时长超过延迟时长的任务,会等上一个任务执行完之后,下一个任务才开始执行,此时,延时没有任何意义。而scheduleWithFixedDelay是在上一个任务结束执行之后延迟设定时间再执行,是从上一个任务结束时开始计算。