43 基于ScheduledThreadPoolExecutor实现定时任务
Diego38 25 1

1. 前言

前面我们已经对ScheduledThreadPoolExecutor的使用和原理做了分析,在JDK1.5之前,实际上还有一个类也可以实现定时任务,那就是Timer,但是Timer有很多问题,因此才有了ScheduledThreadPoolExecutor。

本节我们就将ScheduledThreadPoolExecutor与Timer进行下对比。

2. 基于ScheduledThreadPoolExecutor实现定时任务

在JDK1.5 之前Timer是实现定时任务的首选方案,但是它有个缺点,即如果一个任务的执行过程比较耗时,将会导致其他任务的时效性问题,而且Timer是不捕获异常的,导致我们无法排查任务执行的问题。

接下来编写一个Timer执行定期输出当前的时间的例子:

public class TimerTest {

    public static void main(String[] args) throws ParseException {
        Timer timer = new Timer();
        SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date time = dateFormatter.parse("2021/01/04 18:40:00");
        //让在指定的时刻执行(如果是过去时间会立马执行 如果是将来时间 那就等吧)
        timer.schedule(new CustomTimerTask(), time);
        timer.schedule(new CustomTimerTask() , 1000);
    }

    //Timer要求执行任务,必须要继承TimerTask,然后在run方法中填写任务。
    static class CustomTimerTask extends TimerTask {
        public void run() {
            System.out.println("当前时间为" + new Date());
        }
    }
}
  • Timer支持指定某个时间点执行,也支持一次货多次的定时任务
  • Timer要求任务必须要继承TimerTask
  • 在schedule之后不能返回类型ScheduledFutureTask的对象,无法进行取消和结果获取

Timer除了时效性问题,功能上也不如ScheduledThreadPoolExecutor,目前已经很少使用了,建议大家以后定时任务弃用Timer,改用 ScheduledThreadPoolExecutor。

以下是ScheduledThreadPoolExecutor的代码样例:

public class ScheduledTest {


    public static void main(String[] args) throws InterruptedException {
        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(10);
        ScheduledFuture<?> future = scheduledThreadPoolExecutor.scheduleWithFixedDelay(() -> System.out.println(new Date()),
                1, 1, TimeUnit.SECONDS);
        Thread.sleep(5000);
        future.cancel(true);
        System.out.println("定时任务取消");
    }
}

输出如下:

Sun Jan 24 02:14:25 CST 2021
Sun Jan 24 02:14:26 CST 2021
Sun Jan 24 02:14:27 CST 2021
Sun Jan 24 02:14:28 CST 2021
定时任务取消

从上述代码看出,ScheduledThreadPoolExecutor功能更加强大,支持Runnable和Callable对象的传入,接入方便,相比Timer有明显的优势。

3. 总结

ScheduledThreadPoolExecutor是定时任务的首选组件,JDK1.5代码中不应该再去使用Timer,应该以ScheduledThreadPoolExecutor替代Timer。

预览图
评论区

索引目录