前言
在本文中,我们将介绍TaskScheduler任务调度框架的核心接口。为了更好地理解这些接口,建议先阅读相关阅读材料。
TaskScheduler与JDK的定时器和线程池密切相关。接下来,我们将详细介绍TriggerContext、SimpleTriggerContext、TaskSchedulerTrigger和CronTrigger等接口。
1. TriggerContext
TriggerContext接口包含以下三个方法:
- lastScheduledExecutionTime():上次计划执行的时间
- lastActualExecutionTime():上次实际执行的时间
- lastCompletionTime():上次完成的时间
需要注意的是,从3.0版本开始,这些方法可能返回null(例如首次执行)。
2. SimpleTriggerContext
SimpleTriggerContext是TriggerContext的一个实现类。
3. TaskSchedulerTrigger
TaskSchedulerTrigger接口定义了以下一个方法:
- nextExecutionTime(TriggerContext triggerContext):获取下次执行时间
4. CronTrigger
CronTrigger接口通过Cron表达式来生成调度计划。例如:
```java
scheduler.schedule(task, new CronTrigger("0 15 9-17 * * MON-FRI"));
```
以上表达式表示在工作日的9-17点之间,每隔15分钟执行一次。
5. CronSequenceGenerator
CronSequenceGenerator是一个用于生成Cron表达式的工具类。
以下是重构后的代码:
```java
import java.util.Date;
public class CronSequenceGenerator {
private String cronExpression;
public CronSequenceGenerator(String cronExpression) {
this.cronExpression = cronExpression;
}
public Date next(Date currentTime) {
// 实现Cron表达式解析和计算下一个执行时间的逻辑
// ...
}
public static void main(String[] args) {
CronSequenceGenerator generator = new CronSequenceGenerator("0 15 * * * MON-FRI");
Date next = generator.next(new Date());
System.out.println(next); // Mon Apr 22 17:15:00 CST 2019
System.out.println(generator.next(next)); // Mon Apr 22 18:15:00 CST 2019
}
}
```
这个类可以用于解析和计算Cron表达式,以获取下一个执行时间。在`main`方法中,我们创建了一个`CronSequenceGenerator`实例,并传入了一个Cron表达式。然后,我们使用`next`方法计算出下一个执行时间,并将其打印出来。
这段代码是Java中的一个方法,用于计算定时任务的下一次执行时间。这个方法是在一个实现了Trigger接口的类中定义的。这个类被称为PeriodicTrigger,它表示一个定期执行的任务触发器。这个方法的主要逻辑如下:
1. 首先获取当前任务的上一次执行时间,如果这个时间不为null,说明任务还没有完成,那么就以当前时间为基础去计算下一次执行时间;
2. 如果当前任务的上一次执行时间为null,说明任务已经完成了,那么就直接使用当前时间作为下一次执行时间;
3. 最后,调用sequenceGenerator的next方法,根据上一次执行时间和当前时间计算出下一次执行时间。
这个方法使用了TaskScheduler接口,它是Spring框架中用于调度任务的核心接口之一。TaskScheduler定义了执行定时任务的主要方法,主要包括:schedule、scheduleOnce、scheduleWithFixedDelay、scheduleWithFixedRate等方法。这些方法根据不同的触发方式调用不同的执行逻辑。
实现类通常会对JDK原生的定时器或线程池组件进行包装,以扩展额外的功能。例如,TaskScheduler就是一个典型的例子。它的主要作用是对Runnable任务进行调度,并支持多种触发规则。
TaskScheduler是Spring框架中的一个核心组件,它主要用于对Runnable任务进行调度和管理。通过使用TaskScheduler,开发人员可以更加灵活地控制任务的执行时机和频率,从而提高应用程序的性能和稳定性。
TaskScheduler的工作原理是通过继承JDK原生的定时器或线程池组件,并在其基础上添加额外的功能。具体来说,TaskScheduler会根据配置的触发规则来确定任务的执行时间,并在指定的时间点启动一个新的线程来执行任务。这样一来,即使在多线程环境下,也可以保证任务的正确性和可靠性。
总之,TaskScheduler是一个非常实用的组件,它可以帮助开发人员更好地管理和调度任务,从而提高应用程序的性能和稳定性。同时,通过使用TaskScheduler,还可以避免一些常见的问题,例如死锁、资源泄漏等。因此,对于需要处理大量任务的开发人员来说,学习并掌握TaskScheduler的使用是非常有必要的。
```java
public interface TaskScheduler { // 提交任务调度请求
// Runnable task:待执行的任务
// Trigger trigger:使用Trigger指定任务调度规则
@Nullable
ScheduledFuture> schedule(Runnable task, Trigger trigger);
// @since 5.0
default ScheduledFuture> schedule(Runnable task, Instant startTime) {
return schedule(task, Date.from(startTime));
}
// 提交任务调度请求,startTime表示它的执行时间
// 注意任务只执行一次,使用startTime指定其启动时间
ScheduledFuture> schedule(Runnable task, Date startTime);
// @since 5.0
default ScheduledFuture> scheduleAtFixedRate(Runnable task, Instant startTime, Duration period) {
return scheduleAtFixedRate(task, Date.from(startTime), period.toMillis());
}
// 使用fixedRate的方式提交任务调度请求,任务首次启动时间由传入参数指定
// task:待执行的任务
// startTime:任务启动时间
// period:两次任务启动时间之间的间隔时间,默认单位是毫秒
ScheduledFuture> scheduleAtFixedRate(Runnable task, Date startTime, long period);
// @since 5.0
default ScheduledFuture> scheduleAtFixedRate(Runnable task, Duration period) {
return scheduleAtFixedRate(task, period.toMillis());
}
// 使用fixedRate的方式提交任务调度请求,任务首次启动时间未设置,任务池将会尽可能早的启动任务
// task:待执行任务
// period:两次任务启动时间之间的间隔时间,默认单位是毫秒
ScheduledFuture> scheduleAtFixedRate(Runnable task, long period);
// @since 5.0
default ScheduledFuture> scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay) {
return scheduleWithFixedDelay(task, Date.from(startTime), delay.toMillis());
}
// 使用fixedDelay的方式提交任务调度请求,任务首次启动时间由传入参数指定
// delay:上一次任务结束时间与下一次任务开始时间的间隔时间,单位默认是毫秒
ScheduledFuture> scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
// @since 5.0
default ScheduledFuture> scheduleWithFixedDelay(Runnable task, Duration delay) {
return scheduleWithFixedDelay(task, delay.toMillis());
}
//
TimerManagerTaskScheduler是Quartz框架中用于管理定时任务的类之一。它实现了TaskScheduler接口中的方法,并提供了一些额外的功能,如定时任务的触发时间、延迟时间等。
ThreadPoolTaskScheduler是Quartz框架中的另一个用于管理线程池的类。它实现了TaskScheduler接口中的方法,并使用线程池来执行定时任务。
ScheduledThreadPoolExecutor是Java中的一个线程池实现类,它可以用于执行定时任务。除了实现TaskScheduler接口中的方法外,它还包含了一些对ScheduledThreadPoolExecutor进行操作的接口,如setRejectedExecutionHandler方法、shutdown方法、shutdownNow方法等。
```java
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler {
// 默认的线程池大小为1
private volatile int poolSize = 1;
// 是否在取消任务时移除任务的策略
private volatile boolean removeOnCancelPolicy = false;
@Nullable
private volatile ErrorHandler errorHandler;
// 内部持有一个JUC的ScheduledExecutorService的引用
@Nullable
private ScheduledExecutorService scheduledExecutor;
/**
* 初始化线程池的执行器。该方法的父类是ExecutorConfigurationSupport,它定义了一些线程池的默认配置。
* @param threadFactory 线程工厂
* @param rejectedExecutionHandler 拒绝策略
* @return ExecutorService实例
*/
protected ExecutorService initializeExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
// 我们发现,如果设置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;
}
/**
* 创建一个新的ScheduledThreadPoolExecutor实例作为最终执行任务的执行器。
* @param poolSize 线程池大小
* @param threadFactory 线程工厂
* @param rejectedExecutionHandler 拒绝策略
* @return ScheduledExecutorService实例
*/
protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
return new ScheduledThreadPoolExecutor(poolSize, threadFactory, rejectedExecutionHandler);
}
/**
* 获取当前活动的线程数。委托给ScheduledThreadPoolExecutor来实现。
* @return 当前活动的线程数
*/
public int getActiveCount() {
if (this.scheduledExecutor == null) {
// Not initialized yet: assume no active threads.
return 0;
}
return getScheduledThreadPoolExecutor().getActiveCount();
}
/**
* 最终交给ScheduledThreadPoolExecutor去执行任务。提交执行一次的任务。submitListenable方法表示:提交执行一次的任务,并且返回一个Future对象供判断任务状态使用。
* @param task 要执行的任务
*/
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()方法关闭线程。以下是一个示例:
```java
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 我会被多次执行~~~
```
以下是根据提供的内容重构的代码:
```java
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
public class ConcurrentTaskSchedulerDemo {
public static void main(String[] args) {
ConcurrentTaskScheduler taskScheduler = new ConcurrentTaskScheduler();
ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
executor.setPoolSize(1);
executor.initialize();
// 执行任务
// 执行一次
executor.schedule(taskScheduler::execute, 0, TimeUnit.SECONDS);
// 周期性执行
}
}
class ConcurrentTaskScheduler implements Runnable {
@Override
public void run() {
System.out.println("pool-" + Thread.currentThread().getName() + " I will be executed multiple times");
}
}
```
输出:
```
pool-2-thread-1 I will be executed multiple times
pool-3-thread-1 I will be executed multiple times
pool-3-thread-1 I will be executed multiple times
pool-3-thread-1 I will be executed multiple times
pool-3-thread-1 I will be executed multiple times
pool-3-thread-1 I will be executed multiple times
```
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();
}
}