0


Springboot使用ThreadPoolTaskScheduler轻量级多线程定时任务框架

简介: Spring注解定时任务使用不是很灵活,如果想要灵活的配置定时任务,可以使用xxl-job 或者 quartz等定时任务框架,但是过于繁琐,可能成本较大。所以可以使用ThreadPoolTaskScheduler来灵活处理定时任务

ThreadPoolTaskScheduler是什么

  1. ThreadPoolTaskScheduler

是 Spring Framework 中的一部分,主要用于调度任务。它基于线程池,可以处理异步任务和定时任务

主要api

  • schedule(Runnable task, Trigger trigger) corn表达式,周期执行
  • schedule(Runnable task, Date startTime) 定时执行
  • scheduleAtFixedRate(Runnable task, Date startTime, long period) 定时周期间隔时间执行。间隔时间单位 TimeUnit.MILLISECONDS
  • scheduleAtFixedRate(Runnable task, long period) 间隔时间以固定速率执行。单位毫秒

固定速率执行不会管上次执行的状态如何

在使用前需要配置下ThreadPoolTaskScheduler

  1. @Configuration
  2. public class SchedulingTaskConfig {
  3. @Bean(name = "myThreadPoolTaskScheduler")
  4. public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
  5. ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
  6. taskScheduler.setPoolSize(60);
  7. taskScheduler.setThreadNamePrefix("task-");
  8. taskScheduler.setAwaitTerminationSeconds(3000);
  9. taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
  10. return taskScheduler;
  11. }
  12. }

cron表达式

  1. @Override
  2. public String startTask() {
  3. ScheduledFuture<?> schedule = myThreadPoolTaskScheduler.schedule(new Runnable() {
  4. @Override
  5. public void run() {
  6. System.out.println("1s执行一次");
  7. }
  8. }, new CronTrigger("0/1 * * * * ?"));

定时执行一次

  1. myThreadPoolTaskScheduler.schedule(new Runnable() {
  2. @Override
  3. public void run() {
  4. System.out.println("定时执行3s后开始执行");
  5. }
  6. },new Date(System.currentTimeMillis() + 3000));

在固定时间以固定速率执行

  1. myThreadPoolTaskScheduler.scheduleAtFixedRate(new Runnable() {
  2. @Override
  3. public void run() {
  4. System.out.println("定时执行3s后开始执行,固定3s执行一次");
  5. }
  6. },new Date(System.currentTimeMillis() + 3000),3000);

任务取消

  1. private ScheduledFuture<?> schedule ;
  2. @Override
  3. public String startTask() {
  4. schedule = myThreadPoolTaskScheduler.scheduleAtFixedRate(new Runnable() {
  5. @Override
  6. public void run() {
  7. System.out.println("定时执行3s后开始执行,固定3s执行一次");
  8. }
  9. }, new Date(System.currentTimeMillis() + 3000), 3000);
  10. return "开启成功";
  11. }
  12. @Override
  13. public String stopTask() {
  14. if (schedule != null){
  15. schedule.cancel(true);
  16. System.out.println("任务取消成功");
  17. return "取消成功";
  18. }
  19. return "取消失败";
  20. }

实现页面控制定时任务开关

将定时任务保存到数据库中,并在页面上实现定时任务的开关,以及更新定时任务时间后重新创建定时任务

数据库实体

  1. @TableName("task")
  2. @Data
  3. public class ScheduleTask {
  4. public interface Update{};
  5. @TableId(type = IdType.AUTO)
  6. @NotNull(message = "任务id不能为空",groups = Update.class)
  7. private Integer id;
  8. @NotBlank(message = "请填写任务执行类")
  9. @TableField("task_clazz")
  10. private String taskClazz;
  11. @NotBlank(message = "请填写任务执行方法")
  12. @TableField("task_method")
  13. private String taskMethod;
  14. @NotBlank(message = "请填写任务执行时间,采用cron格式")
  15. @TableField("cron")
  16. private String cron;
  17. @TableLogic
  18. @TableField("status")
  19. private Integer status;
  20. }

contrloller

  1. @RestController
  2. @RequiredArgsConstructor
  3. public class TaskManagerController {
  4. private final TaskManagerService taskManagerService;
  5. @PostMapping("/addTask")
  6. public Boolean addTask(@RequestBody @Validated ScheduleTask task){
  7. return taskManagerService.addTask(task);
  8. }
  9. @PostMapping("/stopTask/{id}")
  10. public Boolean stopTask(@PathVariable Integer id){
  11. return taskManagerService.stopTask(id);
  12. }
  13. }

service

  1. @Service
  2. @Slf4j
  3. @RequiredArgsConstructor
  4. public class TaskManagerServiceImpl implements TaskManagerService {
  5. private final ScheduleTaskMapper scheduleTaskMapper;
  6. private final TaskManager taskManager;
  7. @Override
  8. public Boolean addTask(ScheduleTask task) {
  9. int i = scheduleTaskMapper.insert(task);
  10. if (i > 0){
  11. TaskRunnable taskRunnable = new TaskRunnable(task.getTaskClazz(), task.getTaskMethod());
  12. taskManager.addTask(String.valueOf(task.getId()),taskRunnable,task.getCron());
  13. return true;
  14. }
  15. return false;
  16. }
  17. @Override
  18. public Boolean stopTask(Integer id) {
  19. int i = scheduleTaskMapper.deleteById(id);
  20. if (i> 0){
  21. taskManager.stopTask(String.valueOf(id));
  22. return true;
  23. }
  24. return false;
  25. }
  26. }

TaskRunnable

通过此类获取具体的执行方法

  1. @Slf4j
  2. public class TaskRunnable implements Runnable{
  3. /**
  4. * 定时任务类
  5. */
  6. private final String clazz;
  7. /**
  8. * 定时任务方法
  9. */
  10. private final String methodName;
  11. public TaskRunnable(String clazz, String methodName) {
  12. this.clazz = clazz;
  13. this.methodName = methodName;
  14. }
  15. @Override
  16. public void run() {
  17. try {
  18. //获取类
  19. Object bean = SpringContextUtils.getBean(clazz);
  20. //获取方法
  21. Method method = bean.getClass().getDeclaredMethod(methodName);
  22. //设置方法可用
  23. ReflectionUtils.makeAccessible(method);
  24. //执行方法
  25. method.invoke(bean);
  26. } catch (Exception e) {
  27. log.error("获取方法信息报错:{}",e.getMessage());
  28. throw new RuntimeException(e);
  29. }
  30. }
  31. }

任务调度类

  1. @Component
  2. @RequiredArgsConstructor
  3. @Slf4j
  4. public class TaskManager {
  5. private final ThreadPoolTaskScheduler myThreadPoolTaskScheduler;
  6. public static ConcurrentHashMap<String, ScheduledFuture<?>> cache = new ConcurrentHashMap<>();
  7. /**
  8. * 创建定时任务
  9. * @param key 任务key
  10. * @param taskRunnable 当前线程
  11. * @param cron 定时任务cron
  12. */
  13. public void addTask(String key ,TaskRunnable taskRunnable ,String cron){
  14. //取消任务
  15. this.stopTask(key);
  16. ScheduledFuture<?> schedule = myThreadPoolTaskScheduler.schedule(taskRunnable, new CronTrigger(cron));
  17. if (schedule != null){
  18. cache.put(key,schedule);
  19. log.info("当key为{}的定时任务创建成功",key);
  20. }
  21. }
  22. public void stopTask(String key){
  23. if (cache.get(key) == null){
  24. log.info("当前没有key为{}的定时任务",key);
  25. return;
  26. }
  27. ScheduledFuture<?> scheduledFuture = cache.get(key);
  28. if (scheduledFuture != null){
  29. scheduledFuture.cancel(true);
  30. cache.remove(key);
  31. log.info("当前key为{}的定时任务已取消",key);
  32. }
  33. }
  34. }

工具类

  1. @Component
  2. public class SpringContextUtils implements ApplicationContextAware {
  3. private static ApplicationContext context;
  4. @Override
  5. public void setApplicationContext(ApplicationContext applicationContext) {
  6. SpringContextUtils.context = applicationContext;
  7. }
  8. public static Object getBean(String name){
  9. return context.getBean(name);
  10. }
  11. }

方法测试

  1. @Slf4j
  2. @Component(value = "testTask")
  3. public class TestTask {
  4. public void taskMethod(){
  5. log.info(String.format("调用了当前定时任务"));
  6. }
  7. }

标签: spring boot java spring

本文转载自: https://blog.csdn.net/m0_73363097/article/details/142419944
版权归原作者 又是努力搬砖的一年 所有, 如有侵权,请联系我们删除。

“Springboot使用ThreadPoolTaskScheduler轻量级多线程定时任务框架”的评论:

还没有评论