1.整合SpringTask
1.1.Springboot有起步依赖,无需添加jar包来使用SpringTask,需要两步即可整合Srpingtask
1.1.1.在项目启动类添加@EnableScheduling
@SpringBootApplication
@EnableScheduling
public class AaApplication extends SpringBootServletInitializer {
/**
* jar包启动:执行SpringBootApplication的run方法,启动IOC容器,然后创建嵌入式Servlet容器
* @param args
*/
public static void main(String[] args) {
System.out.println("args---------------"+args);
SpringApplication springApplication=new SpringApplication(AaApplication.class);
//关闭Banner
springApplication.setBannerMode(Banner.Mode.OFF);
springApplication.run(args);
}
}
1.1.2.在Springtask业务类添加@Component(类上,交给Spring容器管理)以及@Scheduled(方法上)
package com.zyp.springtask;
import cn.hutool.core.date.DateUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @author syl
* @description 学习SpringTask
* @since 2022/6/8
*/
@Component
public class SpringTaskTest {
@Scheduled(fixedRate = 1000)
public void task1() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+":task1--->"+ DateUtil.date());
Thread.sleep(2000);
}
@Scheduled(fixedDelay = 2000)
public void task2() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+":task2--->"+ DateUtil.date());
}
}
1.2.Scheduled注解属性解释
1.2.1.@Scheduled(fixedRate = 1000):上一次执行开始时间点之后1秒再执行,等价于@Scheduled(fixedRateString = “1000”)
1.2.2.@Scheduled(fixedDelay = 2000):上一次执行结束之后2秒再执行,等价于@Scheduled(fixedDelayString = “2000”)
1.2.3.@Scheduled(initialDelay = 1000,fixedDelay=2000):第一次执行延后1秒,后面等上一次执行结束之后2秒再执行
1.2.4.@Scheduled(cron = “*/1 * * * * *”),支持cron表达式,当前表示一秒执行一次
注:
0 0 * * * * 整点执行一次.
*/10 * * * * * 每十秒执行一次
0 0 8-10 * * * 每天8点、9点和10点执行
0 0 6,19 * * * 每天上午6:00和下午7:00执行。
0 0/30 8-10 * * * 8-10点之间30分钟执行一次
0 0 9-17 * * MON-FRI 每个工作日9-17点之间整点执行
0 0 0 25 12 ? 圣诞节执行
秒 分 时 天 月 星期几
2.Springtask默认特性介绍
2.1.单线程、串行、无序
@Component
public class SpringTaskTest {
@Scheduled(fixedRateString = "1000")
public void task1() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+":task1--->"+ DateUtil.date());
Thread.sleep(2000);
}
@Scheduled(fixedDelay=2000)
public void task2() {
System.out.println(Thread.currentThread().getName() + ":task2--->" + DateUtil.date());
}
}
执行结果如图
从图中可以看出执行的线程名称一致,并且到task2执行的时候结果task1在执行,说明单线程且串行
@Component
public class SpringTaskTest {
@Scheduled(cron = "*/1 * * * * *")
public void task1() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+":task1--->"+ DateUtil.date());
Thread.sleep(2000);
}
@Scheduled(cron = "*/1 * * * * *")
public void task2() {
System.out.println(Thread.currentThread().getName() + ":task2--->" + DateUtil.date());
}
}
从图中task1和task2执行先后顺序不固定
3.Springboot并行执行与异步执行
package com.zyp.springtask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @author syl
* @description 多定时任务的并行调度与异步调度
* @since 2022/6/8
*/
@Configuration
@Slf4j
public class SpringTaskConfig implements SchedulingConfigurer, AsyncConfigurer {
/**
* 并行调度
* @param taskRegistrar
*/
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setTaskScheduler(taskScheduler());
}
@Bean
public TaskScheduler taskScheduler(){
ThreadPoolTaskScheduler threadPoolTaskScheduler=new ThreadPoolTaskScheduler();
//配置线程池大小
threadPoolTaskScheduler.setPoolSize(10);
//线程名称前缀
threadPoolTaskScheduler.setThreadNamePrefix("spring-task-scheduler-");
//线程池关闭时最大等待时间,确保最后一定关闭
threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
//线程池关闭时等待所有任务执行结束
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
//丢弃任务策略
threadPoolTaskScheduler.setRejectedExecutionHandler( new ThreadPoolExecutor.AbortPolicy());
return threadPoolTaskScheduler;
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor=new ThreadPoolTaskExecutor();
//配置核心线程数
threadPoolTaskExecutor.setCorePoolSize(10);
//配置最大线程数
threadPoolTaskExecutor.setMaxPoolSize(20);
//线程超时时间
threadPoolTaskExecutor.setKeepAliveSeconds(100);
//队列容量
threadPoolTaskExecutor.setQueueCapacity(50);
//线程名称前缀
threadPoolTaskExecutor.setThreadNamePrefix("spring-task--executor-");
//线程池关闭时最大等待时间,确保最后一定关闭
threadPoolTaskExecutor.setAwaitTerminationSeconds(60);
//线程池关闭时等待所有任务执行结束
threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
//丢弃任务策略
threadPoolTaskExecutor.setRejectedExecutionHandler( new ThreadPoolExecutor.CallerRunsPolicy());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SpringTaskExceptionHandler();
}
class SpringTaskExceptionHandler implements AsyncUncaughtExceptionHandler{
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
log.error("SpringTaskExceptionHandler execute error",params);
}
}
}