ScheduledExecutorService 实现延迟任务与周期任务

2016-08-17 19:15:03   最后更新: 2016-08-17 19:15:03   访问数量:698




延迟任务就是诸如“在 100ms 以后执行”这样的任务,而周期任务则是“每 10ms 执行一次”这样的任务

延迟任务与周期任务通常通过 Timer 类负责实现和管理,但是 Timer 类是基于绝对时间而不是相对时间的调度机制,系统时钟的变化会直接影响到 Timer 的执行结果,这是 Timer 的一个明显的缺陷,另一个缺陷在于 Timer 在执行所有定时任务时只会创建一个线程,所有任务的调度延迟时间都是基于上一个任务的结束时间,这样如果某个任务执行时间过长,那么将会破坏其他任务的执行,同时,一旦任务抛出了一个未知的异常,由于 Timer 线程不捕获异常也并不会尝试恢复,因此他会彻底停止执行和调度,这个问题通常被称为“线程泄漏”

ScheduledThreadPoolExecutor 是替代 Timer 的一个比较好的组件,他是通过相对时间进行控制的,不依赖于系统时钟,同时任务的每次执行时间都是基于上一次任务的开始时间计算,结合并发的特性,实现了每次调度不依赖于每次实际的任务执行时间,通过 Executors 对象的工厂方法 newScheduledThreadPool 可以创建 ScheduledExecutorService 对象

 

下面的代码实现了在一分钟内以2秒为周期周期写入log的功能:

package com.techlog.test.service; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; /** * Created by techlog on 16/8/16. */ @Service public class Beep { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Beep.class); private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); public void beepForOneMinute() { final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(() -> LOGGER.info("deep"), 2, 2, TimeUnit.SECONDS); scheduler.schedule(() -> { beeperHandle.cancel(true); scheduler.shutdown(); }, 1, TimeUnit.MINUTES); } }

 

 

可以看到,方法中只用两行代码就实现了一个定时器的周期计时与取消,这主要得益于 lamda 表达式的简洁特性:

java8 新特性

 

scheduleAtFixedRate 方法实现了按照指定频率周期执行任务

它具有下列参数:

  1. Runnable 对象,即每次调度线程中的实际任务
  2. long initialDelay,初次执行前的等待时间
  3. long period,每次调度的时间间隔
  4. TimeUnit unit,时间单位

通过这四个参数,可以灵活的实现周期任务和定时任务的各种需求

 

scheduleAtFixedRate 方法设定的 period 是以每次任务开始时间为基准的相对时间间隔

如果要实现每次任务开始时间以上次任务结束时间为基准的相对时间间隔就需要使用 executeFixedDelay 方法了

他同样具有四个参数:

  1. Runnable 对象,即每次调度线程中的实际任务
  2. long initialDelay,初次执行前的等待时间
  3. long delay,每次调度相对上次任务结束时间的时间间隔
  4. TimeUnit unit,时间单位

 

上述代码中还用到了另一个方法:schedule,这个方法没有 initialDelay,任务会立即以周期进行执行,他与 executeFixedDelay 同样是相对上次任务结束时间调度的周期任务方法

 






技术帖      龙潭书斋      线程      线程池      并发      java      timer      executor      executorservice      schedule      executors      调度     


京ICP备15018585号