SpringBoot基于SchedulingConfigurer接口实现动态定时任务(二)

大千世界,茫茫人海,相识就是一种缘分。若此篇文章对您有帮助,点个赞或点个关注呗!

前言

上一篇博客 Springboot基于@EnableScheduling注解实现定时任务(一) 适用于简单的阻塞执行的定时任务

  • 缺点
    1、多个定时任务使用同一个调度线程,所以任务是阻塞执行,执行效率低;
    2、如果出现任务阻塞,导致一些定时业务不能按照预定时间执行。
  • 优点
    1、配置简单,基于注解就可以实现定时任务;
    2、使用于单个后台线程执行周期任务,并且保证按顺序执行。

SchedulingConfigurer接口实现动态定时任务
实现SchedulingConfigure接口,重写configureTasks方法,添加需执行的定时任务;接下来我会模拟实际通用业务场景实现定时任务操作,定时任务无非就是按照预设执行规则,定时执行具体的业务;

1. 创建数据库
用来存储记录需定时执行的业务方法,处理好具体的业务逻辑,定时间隔时间通过数据库获取,方便在不需要改代码的同时,实现一次部署,动态调整间隔时间;
在这里插入图片描述
服务启动后,先将实现类需要执行的业务方法,通过反射机制存储到数据库中,任务间隔时间可设置默认值,依据不同需求再修改;
2. 获取需定时执行的业务方法,存储到数据库中

TaskService需定时执行的业务方法接口

public interface TaskService {
	/**
	 *同步更新需定时执行的业务方法(省略TaskInfo类)
	 */
	List<TaskInfo> taskList();
	/**
	 *定时任务方法一
	 */
	int taskOne(String info); 
	/**
	 *定时任务方法二
	 */
	int taskTwo(String info); 
}

TaskServiceImpl需定时执行的业务方法实现类


```java
@Service
@Slf4j
public class TaskServiceImpl implements TaskService{
    @Override
    public List<TaskInfo> taskList() {
        List<String> task= new ArrayList<>();
        //反射获取TaskServiceImpl实现类的业务方法
        Method[] methods = TaskServiceImpl .class.getMethods();
        //存储记录业务方法
        Map<String, Method> map= new HashMap<>();
        //因为通过反射获取的包含无用方法,可以利用自定义注解标识(AnnotationSign)过滤,我们需要执行的方法
        for (Method method: methods) {
        	//判断注解标识,并且返回值为int (定时任务无非就是做一些关联第三方接口,在自己本地做一些增删改查
            if (method.isAnnotationPresent(AnnotationSign.class) && m.getReturnType().equals(int.class)) {
                AnnotationSign anno = methodm.getAnnotation(AnnotationSign.class);
                if (anno != null) {
               	   String name = method.getName()
                    //通过Mapper层存储服务的参数
                    task.add(tag);
                    map.put(name , methodm);
                }
            }
        }
    }
    @Override
    @AnnotationSign("定时任务方法一")
    public int taskOne(String info){
    	log.info(Thread.currentThread().getName()+"执行定时任务方法一");
    } 
    @Override
    @AnnotationSign("定时任务方法二")
    public int taskTwo(String info){
    	log.info(Thread.currentThread().getName()+"执行定时任务方法二");
    } 
}

自定义注解标识@AnnotationSign

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationSign {
    String value() default "";
}

3. 实现SchedulingConfigurer接口,重写configureTasks()方法
Java线程池详解

@Slf4j
@Configuration
public class ScheduledConfigure implements SchedulingConfigurer {
    @Autowired
     private TaskService taskService;
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
    	//创建可调度的线程池
    	scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));   
    	load(scheduledTaskRegistrar, taskService.list(), taskService);
    }
	
	  //将需执行的业务方法,载入到定时任务中
    public void load(ScheduledConfigure scheduled, List<TaskInfo> tasks, TaskService taskService) {
        Map<String, ScheduledFuture<?>> map = scheduled.futures;
        List<TaskInfo> all = tasks== null ? new ArrayList<>() : tasks;
        //对比已加载的定时服务和未加载的定时服务
        for (String key : map.keySet()) {
            List<TaskInfo> select = all.stream().filter(item-> key.equals(item.getTask+ s.getInterval())).collect(Collectors.toList());
            if (select.size() <= 0) {
                scheduled.cancelTask(key);
            } else {
                all.remove(select.get(0));
            }
        }
        for (TaskInfo items: all) {
            Method method = reflects.get(items.getSyncTag());
            if (method != null) {
            //获取间隔时间,单位为分钟
                int interval = sync.getInterval() * 60000;
                scheduled.addTask(sync.getSyncTag() + sync.getInterval(), new FixedDelayTask(() -> {
                    int res = -1;
                    try {
                        res = (int) method.invoke(service, sync.getTask());
                    } catch (Exception ex) {
                         e.printStackTrace();
                    }     
                }, interval, interval));
            }
        }
    }
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

能先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值