前言
在日常的开发中,免不了会遇到需要定时执行某些任务的情况,比如定时清理日志、定时发送通知等。我了解到的处理定时任务的解决方案主要有三种:
TimerScheduledExecutorService@Scheduled- 其他
今天主要介绍前两个的用法,@Scheduled注解以后在SpringBoot相关文章会进行介绍。
Timer
构造方法
public Timer()public Timer(boolean isDaemon)
构造方法常用的有以上两个,第一个Timer执行任务的线程默认是非守护线程,第二个Timer可以根据需要设置成守护线程,比如用来收集信息的统计任务不会影响系统的正常运行,可以设置成守护线程。
定时方法
public void schedule(TimerTask task, Date time)
在指定的时间time执行任务task,如果time是过去的时间,那么就会立即执行
public void schedule(TimerTask task, Date firstTime, long period)
在指定的时间firstTime开始执行任务task,之后每隔period时间再执行一次task
public void schedule(TimerTask task, long delay)
延迟delay时间后执行任务task
public void schedule(TimerTask task, long delay, long period)
延迟delay时间后开始执行任务task,之后每隔period时间再执行一次task
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
在指定的时间firstTime开始执行任务task,之后每隔period时间再执行一次task。这个看似和上面第二个方法是一样的,但是执行时却有些区别,比如firstTime是过去的时间,那么schedule方法会立即执行一次,之后再按间隔时间来重复执行;而scheduleAtFixedRate会计算从firstTime到现在的时间,然后根据时间间隔period计算出需要执行任务的次数,一次性全部执行。
也就是说,schedule对于过去的任务只执行一次,而scheduleAtFixedRate会把过去该执行的任务全部补上。
public void scheduleAtFixedRate(TimerTask task, long delay, long period)
延迟delay时间后开始执行任务task,之后每隔period时间再执行一次task。。
ScheduledExecutorService
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
延迟delay时间后执行任务command,返回结果是ScheduledFuture,可以通过get()方法来等待任务执行完成,但是get()方法返回的结果是null。
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
延迟delay时间后执行任务callable,返回结果是ScheduledFuture,可以通过get()方法来等待任务执行完成,并且get()方法会返回任务的执行结果。
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
延迟initialDelay时间后开始执行任务,之后每隔period时间再重复执行一次。period计算的是两个任务开始时间的间隔,到period时间后如果上一个任务没有执行完,那么会等待上一个任务执行完后立即执行本次任务
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
延迟initialDelay时间后开始执行任务,之后每隔period时间再重复执行一次。period计算的是上一个任务结束时间到本次任务的开始时间之间的间隔,上一个任务结束之后才会计算period时间,然后执行下一个任务。
Timer和ScheduledExecutorService区别
Timer使用的是同一个线程执行任务,而ScheduledExecutorService可以通过指定线程池的大小来控制执行任务的线程数量。