ThreadPoolTaskScheduler
包装Java Concurrent中的ScheduledThreadPoolExecutor类,大多数场景下都使用它来进行任务调度。
除实现了TaskScheduler接口中的方法外,它还包含了一些对ScheduledThreadPoolExecutor进行操作的接口
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler { ... // 默认的size 是1 private volatile int poolSize = 1; private volatile boolean removeOnCancelPolicy = false; @Nullable private volatile ErrorHandler errorHandler; // 内部持有一个JUC的ScheduledExecutorService 的引用 @Nullable private ScheduledExecutorService scheduledExecutor; ... // 初始化线程池的执行器~~~~ 该方法的父类是ExecutorConfigurationSupport // 它定义了一些线程池的默认配置~~~~~ @Override protected ExecutorService initializeExecutor( ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) { // 我们发现,如果set PoolSize,那么它的size就是1 this.scheduledExecutor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler); if (this.removeOnCancelPolicy) { if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) { ((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(true); } else { logger.info("Could not apply remove-on-cancel policy - not a Java 7+ ScheduledThreadPoolExecutor"); } } return this.scheduledExecutor; } // 就是new一个ScheduledThreadPoolExecutor 来作为最终执行任务的执行器 protected ScheduledExecutorService createExecutor( int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) { return new ScheduledThreadPoolExecutor(poolSize, threadFactory, rejectedExecutionHandler); } ... //获取当前活动的线程数 委托给ScheduledThreadPoolExecutor来做得 public int getActiveCount() { if (this.scheduledExecutor == null) { // Not initialized yet: assume no active threads. return 0; } return getScheduledThreadPoolExecutor().getActiveCount(); } // 显然最终就是交给ScheduledThreadPoolExecutor去执行了~~~ // 提交执行一次的任务 // submit\submitListenable方法表示:提交执行一次的任务,并且返回一个Future对象供判断任务状态使用 @Override public void execute(Runnable task) { Executor executor = getScheduledExecutor(); try { executor.execute(errorHandlingTask(task, false)); } catch (RejectedExecutionException ex) { throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); } } ... }
使用它前必须得先调用initialize()【初始化方法】,有shutDown()方法,执行完后可以关闭线程
Demo:
public static void main(String[] args) { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); taskScheduler.setPoolSize(2); taskScheduler.initialize(); // 务必调用此方法来启动 // 执行任务 // 执行一次 taskScheduler.execute(() -> System.out.println(Thread.currentThread().getName() + " 我只会被执行一次~~~")); // 周期性执行 taskScheduler.schedule(() -> System.out.println(Thread.currentThread().getName() + " 我会被多次执行~~~"), new CronTrigger("0/2 * * * * ?")); // 此处:若你有周期性的任务,这里不要shutdown() //taskScheduler.shutdown(); }
输出:
ThreadPoolTaskScheduler-1 我只会被执行一次~~~ ThreadPoolTaskScheduler-1 我会被多次执行~~~ ThreadPoolTaskScheduler-2 我会被多次执行~~~ ThreadPoolTaskScheduler-2 我会被多次执行~~~ ThreadPoolTaskScheduler-2 我会被多次执行~~~ ThreadPoolTaskScheduler-1 我会被多次执行~~~ ThreadPoolTaskScheduler-2 我会被多次执行~~~ ThreadPoolTaskScheduler-2 我会被多次执行~~~
发现每次都可能被不同的线程去执行(当然我们这里只放了两个~~~)
ConcurrentTaskScheduler
以单个线程方式执行定时任务,适用于简单场景;(以当前线程执行任务。如果任务简单,可以直接使用这个类来执行。快捷方便。)
PS:这是单线程运行
Demo:
public static void main(String[] args) { ConcurrentTaskScheduler taskScheduler = new ConcurrentTaskScheduler(); // 执行任务 // 执行一次 taskScheduler.execute(() -> System.out.println(Thread.currentThread().getName() + " 我只会被执行一次~~~")); // 周期性执行 taskScheduler.schedule(() -> System.out.println(Thread.currentThread().getName() + " 我会被多次执行~~~"), new CronTrigger("0/2 * * * * ?")); // 此处:若你有周期性的任务,这里不要shutdown() //taskScheduler.shutdown(); }
输出:
pool-2-thread-1 我只会被执行一次~~~ pool-3-thread-1 我会被多次执行~~~ pool-3-thread-1 我会被多次执行~~~ pool-3-thread-1 我会被多次执行~~~ pool-3-thread-1 我会被多次执行~~~ pool-3-thread-1 我会被多次执行~~~
执行的线程都是一样的。都是Executors.newSingleThreadScheduledExecutor()这个执行的~~~
DefaultManagedTaskScheduler
它继承自ConcurrentTaskScheduler,在ConcurrentTaskScheduler基础上增加了JNDI的支持。它@since 4.0,这里不多说明
ScheduledTask
定时任务类,内部包装了一个Runnable。
// @since 4.3 发现这个类出现得还是比较晚得 public final class ScheduledTask { // 任务,其实就是很简单的包装了 Runnable。 // 常见的子类有 TriggerTask、CronTask(主要是支持的CronTrigger、cron表达式)、 // FixedDelayTask、FixedRateTask、IntervalTask(前两者得父类) private final Task task; @Nullable volatile ScheduledFuture<?> future; ScheduledTask(Task task) { this.task = task; } //@since 5.0.2 public Task getTask() { return this.task; } // 取消任务 public void cancel() { ScheduledFuture<?> future = this.future; if (future != null) { future.cancel(true); } } @Override public String toString() { return this.task.toString(); } }
总结
这篇文章主要是对Spring得调取系统进行一些重点接口、类进行盘点。其实底层大都是依赖JDK的实现的。
从很多方面可以看出,Spring对JDK底层可谓非常非常的熟悉,才能运用得这么自如。在后面讲解SpringBoot、SpringCloud时依然能体现到这一点。那就是Spring很重重复造轮子,除非它真心觉得你的实现不好~