前言

在本文中,我们将介绍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);

// 周期性执行

executor.schedule(taskScheduler::execute, 0, 2, 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();

}

}