spring揭秘31-spring任务调度02-spring集成任务执行与调度-spring官方文档

文章目录

  • 【README】
  • 【1】spring任务执行器(TaskExecutor)抽象
    • 【1.1】TaskExecutor实现类(执行器)
    • 【1.2】使用TaskExecutor代码实践
  • 【2】spring任务调度抽象(TaskScheduler)
    • 【2.1】Trigger触发器接口
      • 【2.1.1】 Trigger实现类
    • 【2.2】任务调度器(TaskScheduler)实现
  • 【3】任务调度与任务异步执行的注解支持
    • 【3.1】启用调度注解
      • 【3.1.1】@Scheduled与@Async注解源码
    • 【3.2】@Scheduled注解
      • 【2.4.1】以固定频率执行调度任务
      • 【2.4.2】以固定频率及初始延迟执行调度任务
      • 【2.4.3】单次执行的任务设置初始延时
      • 【2.4.4】使用cron表达式配置调度任务
    • 【3.3】@Async注解
      • 【2.5.1】@Async中执行器限定
      • 【2.5.2】使用@Async进行异常管理
  • 【4】xml配置文件task命名空间
    • 【4.1】task:scheduler元素
    • 【4.2】task:executor元素
    • 【4.3】task:scheduled-tasks元素
  • 【5】任务调度与任务异步执行代码实践
    • 【5.1】任务调度代码实践
      • 【5.1.1】task:scheduler元素创建调度器底层原理
    • 【5.2】任务异步执行代码实践
  • 【6】cron表达式(非常重要)
    • 【6.1】cron表达式宏指令
    • 【6.2】使用cron表达式执行调度任务代码实践
  • 【7】使用 Quartz调度器
    • 【7.1】使用JobDetailFactoryBean
    • 【7.2】使用MethodInvokingJobDetailFactoryBean
    • 【7.3】使用Trigger与SchedulerFactoryBean关联job
    • 【7.4】 spirng集成Quartz调度器代码实践
  • 【8】Quartz调度器与java调度线程池ScheduledExecutorService的区别(重要)
    • 【8.1】ScheduledExecutorService调度任务回顾
      • 【8.1.1】每2s执行1次但业务逻辑耗时5s
      • 【8.1.2】每2s执行1次但业务逻辑耗时1s

【README】

本文内容总结自spring官方文档 spring integrates task execution and scheduling, 墙裂推荐;

本文代码,参见: github springDiscover repo 的【chapter31schedule】章节

spring框架使用 TaskExecutorTaskScheduler 接口提供了对任务异步执行与调度的抽象;

  • spring提供了这些接口的实现以支持线程池或委派给CommonJ类库处理。 spring也拥有集成功能以支持使用Quartz调度器进行任务调度。


【1】spring任务执行器(TaskExecutor)抽象

1)执行器概念:执行器是JDK为线程池概念取的名字。执行器名字源于一个事实,即无法保证底层实现是一个池子。一个执行器可能是单线程甚至是同步执行的。spring的抽象隐藏了javase与Jakarta ee环境的细节。

spring的TaskExecutor接口与java.util.concurrent.Executor接口是相同的,前者继承后者。该接口有一个方法 (execute(Runnable task)) 用于接收一个任务在线程池语义与配置下执行。

public interface TaskExecutor extends Executor {
   
    void execute(Runnable task);
}

2)起初,TaskExecutor是为了给spring组件提供线程池抽象而创建的,如ApplicationEventMulticaster, JMS’s AbstractMessageListenerContainer,以及Quartz集成都使用TaskExecutor对池化线程进行抽象。

3)所以:简单理解,spring的任务执行器TaskExecutor,就当做 jdk的Executor来使用



【1.1】TaskExecutor实现类(执行器)

1)spring提供了多个TaskExecutor实现类

  • SyncTaskExecutor:同步运行任务;即每次调用发生在主线程;
  • SimpleAsyncTaskExecutor:不会复用任何线程,每次调用都会开启新线程;(不推荐使用;线程新建与回收非常耗费资源
  • ConcurrentTaskExecutor: 它是 Executor实例的一个适配器;作为ThreadPoolTaskExecutor的替代品通过bean属性公开Executor配置参数;一般不选择ConcurrentTaskExecutor;然而,当ThreadPoolTaskExecutor不够灵活时,ConcurrentTaskExecutor可以是一个替代品;
  • ThreadPoolTaskExecutor: 最通用的任务执行器(推荐);它公开bean属性以配置ThreadPoolExecutor,并包装ThreadPoolExecutor。如果你想要适配不同的Executor,推荐使用ConcurrentTaskExecutor;
  • DefaultManagedTaskExecutor: 它在JSR-236兼容运行时环境中使用JNDI获得的ManagedExecutorService (如Jakarta ee应用服务器),目的是替换CommonJ WorkManager;

2)从6.1开始,ThreadPoolTaskExecutor通过spring生命周期管理提供了暂停与恢复功能,优雅关闭功能。

【SyncTaskExecutor】同步任务执行器;

public class SyncTaskExecutor implements TaskExecutor, Serializable {
   
    public SyncTaskExecutor() {
   
    }

    public void execute(Runnable task) {
   
        Assert.notNull(task, "Runnable must not be null");
        task.run();
    }
}

【SimpleAsyncTaskExecutor】简单异步任务执行器

  • 继承CustomizableThreadCreator,顾名思义,要自行创建线程,所以本文不推荐SimpleAsyncTaskExecutor
  • 实现AsyncListenableTaskExecutor,AsyncListenableTaskExecutor继承 AsyncTaskExecutor,AsyncTaskExecutor继承TaskExecutor;
public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator implements AsyncListenableTaskExecutor, Serializable, AutoCloseable {
   
    public static final int UNBOUNDED_CONCURRENCY = -1;
    public static final int NO_CONCURRENCY = 0;
    private final ConcurrencyThrottleAdapter concurrencyThrottle = new ConcurrencyThrottleAdapter();
    @Nullable
    private VirtualThreadDelegate virtualThreadDelegate;
    @Nullable
    private ThreadFactory threadFactory;
    @Nullable
    private TaskDecorator taskDecorator;
    private long taskTerminationTimeout;
    @Nullable
    private Set<Thread> activeThreads;
    private volatile boolean active = true;
    // ...
}

【ConcurrentTaskExecutor】内部封装了jdk的Executor

public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, SchedulingTaskExecutor {
   
    private static final Executor STUB_EXECUTOR = (task) -> {
   
        throw new IllegalStateException("Executor not configured");
    };
    @Nullable
    private static Class<?> managedExecutorServiceClass;
    private Executor concurrentExecutor; // 内部封装了jdk的Executor 
    private TaskExecutorAdapter adaptedExecutor;
    @Nullable
    private TaskDecorator taskDecorator;    

    public ConcurrentTaskExecutor(@Nullable Executor executor) {
   
        this.concurrentExecutor = STUB_EXECUTOR;
        this.adaptedExecutor = new TaskExecutorAdapter(STUB_EXECUTOR);
        if (executor != null) {
   
            this.setConcurrentExecutor(executor);
        }

    }
    // ...... 
}


【ThreadPoolTaskExecutor】线程池任务执行器, 封装了ThreadPoolExecutor

public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport implements AsyncListenableTaskExecutor, SchedulingTaskExecutor {
   
    private final Object poolSizeMonitor = new Object();
    private int corePoolSize = 1;
    private int maxPoolSize = Integer.MAX_VALUE;
    private int keepAliveSeconds = 60;
    private int queueCapacity = Integer.MAX_VALUE;
    private boolean allowCoreThreadTimeOut = false;
    private boolean prestartAllCoreThreads = false;
    private boolean strictEarlyShutdown = false;
    @Nullable
    private TaskDecorator taskDecorator;
    @Nullable
    private ThreadPoolExecutor threadPoolExecutor;
    private final Map<Runnable, Object> decoratedTaskMap;

    public ThreadPoolTaskExecutor() {
   
        this.decoratedTaskMap = new ConcurrentReferenceHashMap(16, ReferenceType.WEAK);
    }
    // ......
}

【SchedulingTaskExecutor】调度任务执行器

public interface SchedulingTaskExecutor extends AsyncTaskExecutor {
   
    default boolean prefersShortLivedTasks() {
   
        return true;
    }
}

【AsyncTaskExecutor】异步任务执行器,继承自 TaskExecutor

public interface AsyncTaskExecutor extends TaskExecutor {
   
  // ...... 
  
    default Future<?> submit(Runnable task) {
   
        FutureTask<Object> future = new FutureTask(task, (Object)null);
        this.execute(future);
        return future;
    }

    default <T> Future<T> submit(Callable<T> task) {
   
        FutureTask<T> future = new FutureTask(task);
        this.execute(future, Long.MAX_VALUE);
        return future;
    }

    default CompletableFuture<Void> submitCompletable(Runnable task) {
   
        return CompletableFuture.runAsync(task, this);
    }

    default <T> CompletableFuture<T> submitCompletable(Callable<T> task) {
   
        return FutureUtils.callAsync(task, this);
    }
}

【小结】任务执行器的类层次关系:(TaskExecutor继承jdk的Executor)

  • SyncTaskExecutor实现了 TaskExecutor;
  • ConcurrentTaskExecutor:实现了SchedulingTaskExecutor, SchedulingTaskExecutor继承自AsyncTaskExecutor, AsyncTaskExecutor继承自TaskExecutor;
  • ThreadPoolTaskExecutor:实现了SchedulingTaskExecutor, …同上;


【1.2】使用TaskExecutor代码实践

【TaskExecutorExample】业务场景:异步打印消息

public class TaskExecutorExample {
   

    private class MessagePrinterTask implements Runnable {
   
        private String message;
        public MessagePrinterTask(String message) {
   
            this.message = message;
        }
        public void run() {
   
            System.out.println("线程id=" + Thread.currentThread().getId() + ", message=" + message);
            try {
   
                TimeUnit.MILLISECONDS.sleep(200);
            } catch (InterruptedException e) {
   
                throw new RuntimeException(e);
            }
        }
    }

    private TaskExecutor taskExecutor;
    public TaskExecutorExample(TaskExecutor taskExecutor) {
   
        this.taskExecutor = taskExecutor;
    }

    public void printMessages() {
   
        for(int i = 0; i < 25; i++) {
   
            taskExecutor.execute(new MessagePrinterTask("Message" + i));
        }
    }
    // main函数: 案例执行入口
    public static void main(String[] args) {
   
        ThreadPoolTaskExecutor threadPoolTaskExecutor = buildThreadPoolTaskExecutor();
        new TaskExecutorExample(threadPoolTaskExecutor).printMessages();
        threadPoolTaskExecutor.shutdown();
    }
    private static ThreadPoolTaskExecutor buildThreadPoolTaskExecutor() {
   
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        // 设置属性前,必须先调用initialize()初始化Executor,实际底层调用 ThreadPoolTaskExecutor#initializeExecutor()
        threadPoolTaskExecutor.initialize();
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true); // 等待任务执行完成后再关闭执行器
        threadPoolTaskExecutor.setCorePoolSize(2);
        threadPoolTaskExecutor.setMaxPoolSize(3);
        threadPoolTaskExecutor.setKeepAliveSeconds(0);
        threadPoolTaskExecutor.setQueueCapacity(100);
        return threadPoolTaskExecutor;
    }
}

【执行效果】

线程id=15, message=Message0
线程id=16, message=Message1
线程id=16, message=Message2
线程id=15, message=Message3
线程id=16, message=Message5
线程id=15, message=Message4
线程id=16, message=Message6
线程id=15, message=Message7
线程id=16, message=Message8
线程id=15, message=Message9
线程id=16, message=Message10
线程id=15, message=Message11
线程id=16, message=Message12
线程id=15, message=Message13
线程id=15, message=Message14
线程id=16, message=Message15
线程id=15, message=Message16
线程id=16, message=Message17
线程id=15, message=Message18
线程id=16, message=Message19
线程id=15, message=Message20
线程id=16, message=Message21
线程id=15, message=Message22
线程id=16, message=Message23
线程id=15, message=Message24

【代码解说】

  • ThreadPoolTaskExecutor的setter方法设置的属性值: 可以在xml文件中通过bean属性进行设置;
  • 把ThreadPoolTaskExecutor作为TaskExecutor,ThreadPoolTaskExecutor内部封装了ThreadPoolExecutor ;


【2】spring任务调度抽象(TaskScheduler)

1)spring有一个TaskScheduler接口,定义了很多方法用于调度任务在未来某个时间点执行;

public interface TaskScheduler {
   
    default Clock getClock() {
   
        return Clock.systemDefaultZone();
    } 
    ScheduledFuture<?> schedule(Runnable task, 

你可能感兴趣的:(spring揭秘31-spring任务调度02-spring集成任务执行与调度-spring官方文档)