springboot的定时任务
定时任务有三种,现在我学习的是springboot里面的一种,是比较简单的,下面是一些dome
package com.ljquan.test.dome.test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @className ScheduledService
* @Description: 定时任务学习
* @Author ljquan
* @Date 2022/05/19 10:40:54
* @Version 1.0.0
*/
@Component
@Slf4j
public class ScheduledService {
/*
* 这三种是单线程的
* */
@Scheduled(cron = "0/5 * * * * * ")
public void test() {
log.info("测试定时任务调度cron{}", System.currentTimeMillis());
}
@Scheduled(cron = "0/5 * * * * * ")
public void test2() {
log.info("测试定时任务调度2cron{}", System.currentTimeMillis());
}
@Scheduled(fixedRate = 5000)
public void scheduled1() {
log.info("=====>>>>>使用fixedRate{}", System.currentTimeMillis());
}
@Scheduled(fixedDelay = 5000)
public void scheduled2() {
log.info("=====>>>>>fixedDelay{}", System.currentTimeMillis());
}
/*
* 在主类上使用@EnableScheduling注解开启对定时任务的支持,然后启动项目
可以看到三个定时任务都已经执行,并且使同一个线程中串行执行,
* 如果只有一个定时任务,这样做肯定没问题,
* 当定时任务增多,如果一个任务卡死,会导致其他任务也无法执行。*/
}
在主类上使用@EnableScheduling注解开启对定时任务的支持,然后启动项目
package com.ljquan.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 测试Dome启动成功 ლ(´ڡ`ლ)゙\"");
}
}
输出结果:
(♥◠‿◠)ノ゙ 测试Dome启动成功 ლ(´ڡ`ლ)゙"
2022-05-19 11:29:25.006 INFO 15868 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : 测试定时任务调度cron1652930965006
2022-05-19 11:29:25.007 INFO 15868 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : 测试定时任务调度2cron1652930965007
2022-05-19 11:29:27.843 INFO 15868 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : =====>>>>>使用fixedRate1652930967843
2022-05-19 11:29:27.843 INFO 15868 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : =====>>>>>fixedDelay1652930967843
2022-05-19 11:29:30.010 INFO 15868 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : 测试定时任务调度2cron1652930970010
2022-05-19 11:29:30.010 INFO 15868 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : 测试定时任务调度cron1652930970010
2022-05-19 11:29:32.836 INFO 15868 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : =====>>>>>使用fixedRate1652930972836
2022-05-19 11:29:32.852 INFO 15868 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : =====>>>>>fixedDelay1652930972852
可以看到,多个定时任务都是同一个线程的,如果一个定时任务出现问题,就会导致其他任务也会出现问题,所以就使用多线程的方式。
springboot的多线程 @Async 的使用、自定义Executor的配置方法
结合上面的代码
首先配置Executor,也就是重新配置我们的线程池执行器
package com.ljquan.test.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @className ExecutorConfig
* @Description: 设置多线程的配置
* @Author ljquan
* @Date 2022/05/19 11:22:14
* @Version 1.0.0
*/
@Configuration
public class ExecutorConfig {
/**
* 设置 ThreadPoolExecutor 的核心池大小.
*/
private final int corePoolSize = 10;
/**
* 设置 ThreadPoolExecutor 的最大池大小.
*/
private final int maxPoolSize = 200;
/**
* 设置 ThreadPoolExecutor 的 BlockingQueue 的容量.
*/
private final int queueCapacity = 10;
/**
* 异步一
*
* @return {@code Executor}
*/
@Bean
public Executor Async1() {
//线程池任务执行器 创建一个线程池
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//设置核心池大小
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
//设置队列容量
executor.setQueueCapacity(queueCapacity);
//设置线程前缀
executor.setThreadNamePrefix("测试线程demo1-");
executor.initialize();
return executor;
}
/**
* async2
*
* @return {@code Executor}
*/
@Bean
public Executor Async2() {
//线程池任务执行器 创建一个线程池
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//设置核心池大小
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
//设置队列容量
executor.setQueueCapacity(queueCapacity);
//设置线程前缀
executor.setThreadNamePrefix("222测试线程demo2-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
//设置拒绝执行处理程序
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
// 类似的如果还有其他线程,也可以继续给其他线程配置对应的线程池
}
配置好了,就可以去使用了@Async(“Async1”)去对应的方法或者类里面去执行了,这样就相当于配置好了
@Async("Async1")
@Scheduled(cron = "0/5 * * * * * ")
public void test() {
log.info("测试定时任务调度cron{}", System.currentTimeMillis());
}
类似于这样,就把当前的方法放进线程池里面执行了
执行结果:
(♥◠‿◠)ノ゙ 测试Dome启动成功 ლ(´ڡ`ლ)゙"
2022-05-19 11:42:00.016 INFO 15908 --- [ 测试线程demo1-2] c.l.test.dome.test.ScheduledService : 测试定时任务调度2cron1652931720016
2022-05-19 11:42:00.016 INFO 15908 --- [ 测试线程demo1-1] c.l.test.dome.test.ScheduledService : 测试定时任务调度cron1652931720016
2022-05-19 11:42:00.228 INFO 15908 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : =====>>>>>使用fixedRate1652931720228
2022-05-19 11:42:00.244 INFO 15908 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : =====>>>>>fixedDelay1652931720244
2022-05-19 11:42:05.004 INFO 15908 --- [ 测试线程demo1-3] c.l.test.dome.test.ScheduledService : 测试定时任务调度cron1652931725004
2022-05-19 11:42:05.005 INFO 15908 --- [ 测试线程demo1-4] c.l.test.dome.test.ScheduledService : 测试定时任务调度2cron1652931725005
2022-05-19 11:42:05.240 INFO 15908 --- [ scheduling-1] c.l.test.dome.test.ScheduledService : =====>>>>>使用fixedRate1652931725240
很明显的看到,这些线程都不是同一个线程了。关于springboot的多线程学习完成了。
gitee地址:
https://gitee.com/ljq4551/demo