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

相关文章
|
25天前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
10月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
320 73
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
306 1
|
6月前
|
前端开发 IDE Java
Spring MVC 中因导入错误的 Model 类报错问题解析
在 Spring MVC 或 Spring Boot 开发中,若导入错误的 `Model` 类(如 `ch.qos.logback.core.model.Model`),会导致无法解析 `addAttribute` 方法的错误。正确类应为 `org.springframework.ui.Model`。此问题通常因 IDE 自动导入错误类引起。解决方法包括:删除错误导入、添加正确包路径、验证依赖及清理缓存。确保代码中正确使用 Spring 提供的 `Model` 接口以实现前后端数据传递。
171 0
|
10月前
|
Java Spring
【Spring配置相关】启动类为Current File,如何更改
问题场景:当我们切换类的界面的时候,重新启动的按钮是灰色的,不能使用,并且只有一个Current File 项目,下面介绍两种方法来解决这个问题。
175 10
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
15810 125
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
275 0
Spring高手之路22——AOP切面类的封装与解析
|
Java Spring
idea新建spring boot 项目右键无package及java类的选项
idea新建spring boot 项目右键无package及java类的选项
560 5
|
SQL Java 调度
实时计算 Flink版产品使用问题之使用Spring Boot启动Flink处理任务时,使用Spring Boot的@Scheduled注解进行定时任务调度,出现内存占用过高,该怎么办
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
Java 数据库连接 API
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
1269 1

热门文章

最新文章