【小家Spring】Spring任务调度核心接口(类)之---TaskScheduler(任务调度器)、Trigger(触发器)、ScheduledTask(调度任务)详解(下)

简介: 【小家Spring】Spring任务调度核心接口(类)之---TaskScheduler(任务调度器)、Trigger(触发器)、ScheduledTask(调度任务)详解(下)

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很重重复造轮子,除非它真心觉得你的实现不好~

相关文章
|
8天前
|
存储 安全 Java
|
22天前
|
自然语言处理 JavaScript Java
Spring 实现 3 种异步流式接口,干掉接口超时烦恼
本文介绍了处理耗时接口的几种异步流式技术,包括 `ResponseBodyEmitter`、`SseEmitter` 和 `StreamingResponseBody`。这些工具可在执行耗时操作时不断向客户端响应处理结果,提升用户体验和系统性能。`ResponseBodyEmitter` 适用于动态生成内容场景,如文件上传进度;`SseEmitter` 用于实时消息推送,如状态更新;`StreamingResponseBody` 则适合大数据量传输,避免内存溢出。文中提供了具体示例和 GitHub 地址,帮助读者更好地理解和应用这些技术。
120 0
|
2月前
|
存储 数据采集 Java
Spring Boot 3 实现GZIP压缩优化:显著减少接口流量消耗!
在Web开发过程中,随着应用规模的扩大和用户量的增长,接口流量的消耗成为了一个不容忽视的问题。为了提升应用的性能和用户体验,减少带宽占用,数据压缩成为了一个重要的优化手段。在Spring Boot 3中,通过集成GZIP压缩技术,我们可以显著减少接口流量的消耗,从而优化应用的性能。本文将详细介绍如何在Spring Boot 3中实现GZIP压缩优化。
207 6
|
1月前
|
存储 NoSQL Java
Spring Boot项目中使用Redis实现接口幂等性的方案
通过上述方法,可以有效地在Spring Boot项目中利用Redis实现接口幂等性,既保证了接口操作的安全性,又提高了系统的可靠性。
29 0
|
3月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
40 0
Spring高手之路22——AOP切面类的封装与解析
|
3月前
|
JSON 安全 Java
|
4月前
|
Java Spring
idea新建spring boot 项目右键无package及java类的选项
idea新建spring boot 项目右键无package及java类的选项
195 5
|
3月前
|
存储 SQL Java
|
3月前
|
JavaScript Java Spring
Spring Boot 接口返回文件流
Spring Boot 接口返回文件流
94 0
|
4月前
|
SQL Java 数据库
实时计算 Flink版产品使用问题之Spring Boot集成Flink可以通过什么方式实现通过接口启动和关闭Flink程序
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。