2023-2更文2-ScheduledThreadPool定时任务线程池的使用

199 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情

ScheduledThreadPool定时任务线程池的使用

前文

定时任务线程池是jdk所提供的几种默认线程池之一,它主要是提供给我们一个通过线程池申请线程,并在线程中定时执行逻辑的能力。简单来讲,就是通过定时任务线程池,我们可以按照一定的时间周期,定时从线程池中获取我们所需要的线程,来执行目标任务逻辑。本文将从定时任务线程池的使用及原理两个角度进行总结。

定时任务线程池的使用

要使用线程池,首先我们需要进行线程池的创建,在这里我们采用jdk所提供的线程池构造器来进行线程池的创建:

ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(10);

如上所示,我们创建了一个线程数目为10的定时任务线程池。创建后想要进行任务的发布,则需要调用schedule等方法发布任务。定时任务的发布一共有四种方法,分别是直接发布、发布带执行结果的任务、按照一定频率执行任务(两种),后两种区别是是否考虑前一次任务已经执行完成。第三种需要经过间隔时间等待后,确认前一次任务执行完毕,如果任务未执行完毕则等待执行完毕后立即执行。而第四种仅考虑时间间隔,当时间到达时立即开始执行任务。

image.png

scheduledThreadPoolExecutor.scheduleWithFixedDelay(() -> {
    System.out.println(System.currentTimeMillis() + ":now");
    System.out.println(Thread.currentThread().getName());
},0,1, TimeUnit.SECONDS);

如上面的示例代码,每隔一秒会打印当前时间及当前线程名称,经过执行可以发现,每次执行的线程实际是不一致的。也就是对于定时任务而言,每次会重新拉起一个线程进行任务调度,而不是采用单一线程执行。

定时任务线程池原理

if (isShutdown())
    reject(task);
else {
    super.getQueue().add(task);
    if (isShutdown() &&
        !canRunInCurrentRunState(task.isPeriodic()) &&
        remove(task))
        task.cancel(false);
    else
        ensurePrestart();
}

查看源码可以发现,当我们进行定时任务的调度声明时,会将我们的任务添加到一个现有的队列当中,该队列是DelayedWorkQueue,是一个阻塞队列,同时该队列的容量是无限的。也就是对于任务线程池来说,可以发布的任务并无数量限制。实际上任务的启动及取消,都是通过该队列间接操作。而同样也是通过该队列,来实现按时任务执行的调度。

总结

以上为定时任务线程池的简单应用及原理的概述,该线程池也是开发中非常常用的一种线程池。