Java ScheduledExecutorService 与 Timer

问:说说 Java 中 ScheduledExecutorService 与 Timer 的区别?

答:Timer 计时器具备使任务延迟执行以及周期性执行的功能,但是 Timer 天生存在一些缺陷,所以从 JDK 1.5 开始就推荐使用 ScheduledThreadPoolExecutor(ScheduledExecutorService 实现类)作为其替代工具。

  • 首先 Timer 对提交的任务调度是基于绝对时间而不是相对时间的,所以通过其提交的任务对系统时钟的改变是敏感的(譬如提交延迟任务后修改了系统时间会影响其执行);而 ScheduledThreadExecutor 只支持相对时间,对系统时间不敏感。

  • 接着 Timer 的另一个问题是如果 TimerTask 抛出未检查异常则 Timer 将会产生无法预料的行为,因为 Timer 线程并不捕获异常,所以 TimerTask 抛出的未检查异常会使 Timer 线程终止,所以后续提交的任务得不到执行;而 ScheduledThreadPoolExecutor 不存在此问题。

下面是 ScheduledExecutorService 接口提供的方法如下:

public interface ScheduledExecutorService extends ExecutorService {

    /**
     * 调度一个 Runnable 类型的 task,经过 delay(时间单位由参数 unit 决定)后开始进行调度。
     */
    public ScheduledFuture<?> schedule(Runnable command,
                                       long delay, TimeUnit unit);

    /**
     * 调度一个 Callable 类型的 task,经过 delay(时间单位由参数 unit 决定)后开始进行调度。
     */
    public <V> ScheduledFuture<V> schedule(Callable<V> callable,
                                           long delay, TimeUnit unit);

    /**
     * 周期性调度一个 Runnable 类型的 task,在 delay 后开始调度。
     */
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);

    /**
     * ScheduledExecutorService 相对于 Timer 所特有的方法,固定延迟调度。
     */
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);
}

下面是 ScheduledExecutorService 及其实现类的源码继承关系:

public class ScheduledThreadPoolExecutor
        extends ThreadPoolExecutor
        implements ScheduledExecutorService {
        ......
}

public class ThreadPoolExecutor extends AbstractExecutorService {}
public abstract class AbstractExecutorService implements ExecutorService {}
public interface ExecutorService extends Executor {}

public interface ScheduledExecutorService extends ExecutorService {}
public interface ExecutorService extends Executor {}

可以看见 ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor,所以本质上来说 ScheduledThreadPoolExecutor 是一个线程池,它也有 coorPoolSize 和 workQueue,也接受 Runnable 的子类作为任务,与一般线程池不一样的地方在于它实现了自己的工作队列 DelayedWorkQueue,这个队列会按照一定顺序对队列中的任务进行排序。

而对于 Timer,其实现为 Thread 加 Runnable 组成的列表。

本参考自 ScheduledExecutorService 与 Timer 相关题目解析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容