当前位置: 首页 > article >正文

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

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

ThreadPoolTaskScheduler是什么

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

@Configuration
public class SchedulingTaskConfig {

    @Bean(name = "myThreadPoolTaskScheduler")
    public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(60);
        taskScheduler.setThreadNamePrefix("task-");
        taskScheduler.setAwaitTerminationSeconds(3000);
        taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        return taskScheduler;
    }
}

cron表达式


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

定时执行一次

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

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

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

任务取消

private  ScheduledFuture<?> schedule ;
    @Override
    public String startTask() {

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

        return "开启成功";
    }

    @Override
    public String stopTask() {
        if (schedule != null){
            schedule.cancel(true);
             System.out.println("任务取消成功");
            return "取消成功";
        }
        return "取消失败";
    }

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

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

数据库实体




@TableName("task")
@Data
public class ScheduleTask {
    public interface Update{};

    @TableId(type = IdType.AUTO)
    @NotNull(message = "任务id不能为空",groups = Update.class)
    private Integer id;

    @NotBlank(message = "请填写任务执行类")
    @TableField("task_clazz")
    private String taskClazz;

    @NotBlank(message = "请填写任务执行方法")
    @TableField("task_method")
    private String taskMethod;

    @NotBlank(message = "请填写任务执行时间,采用cron格式")
    @TableField("cron")
    private String cron;

    @TableLogic
    @TableField("status")
    private Integer status;
}

contrloller

@RestController
@RequiredArgsConstructor
public class TaskManagerController {


    private final TaskManagerService taskManagerService;

    @PostMapping("/addTask")
    public Boolean addTask(@RequestBody @Validated ScheduleTask task){
        return taskManagerService.addTask(task);
    }

    @PostMapping("/stopTask/{id}")
    public Boolean stopTask(@PathVariable Integer id){
        return taskManagerService.stopTask(id);
    }
}

service



@Service
@Slf4j
@RequiredArgsConstructor
public class TaskManagerServiceImpl implements TaskManagerService {


    private final ScheduleTaskMapper scheduleTaskMapper;
    private final TaskManager taskManager;
    @Override
    public Boolean addTask(ScheduleTask task) {
        int i = scheduleTaskMapper.insert(task);
        if (i > 0){
            TaskRunnable taskRunnable = new TaskRunnable(task.getTaskClazz(), task.getTaskMethod());
            taskManager.addTask(String.valueOf(task.getId()),taskRunnable,task.getCron());
            return true;
        }
        return false;
    }

    @Override
    public Boolean stopTask(Integer id) {
        int i = scheduleTaskMapper.deleteById(id);
        if (i> 0){
            taskManager.stopTask(String.valueOf(id));
            return true;
        }
        return false;
    }
}

TaskRunnable

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



@Slf4j
public class TaskRunnable implements Runnable{
    /**
     * 定时任务类
     */
    private final String clazz;

    /**
     * 定时任务方法
     */
    private final String methodName;

    public TaskRunnable(String clazz, String methodName) {
        this.clazz = clazz;
        this.methodName = methodName;
    }

    @Override
    public void run() {

        try {
            //获取类
            Object bean = SpringContextUtils.getBean(clazz);
            //获取方法
           Method method = bean.getClass().getDeclaredMethod(methodName);
           //设置方法可用
           ReflectionUtils.makeAccessible(method);
           //执行方法
           method.invoke(bean);
        } catch (Exception e) {
            log.error("获取方法信息报错:{}",e.getMessage());
            throw new RuntimeException(e);
        }
    }
}

任务调度类



@Component
@RequiredArgsConstructor
@Slf4j
public class TaskManager {

    private final ThreadPoolTaskScheduler myThreadPoolTaskScheduler;

    public static ConcurrentHashMap<String, ScheduledFuture<?>> cache = new ConcurrentHashMap<>();

    /**
     * 创建定时任务
     * @param key 任务key
     * @param taskRunnable 当前线程
     * @param cron 定时任务cron
     */
    public void addTask(String key ,TaskRunnable taskRunnable ,String cron){
        //取消任务
        this.stopTask(key);
        ScheduledFuture<?> schedule = myThreadPoolTaskScheduler.schedule(taskRunnable, new CronTrigger(cron));
        if (schedule != null){
            cache.put(key,schedule);
            log.info("当key为{}的定时任务创建成功",key);
        }
    }


    public void stopTask(String key){
        if (cache.get(key) == null){
            log.info("当前没有key为{}的定时任务",key);
            return;
        }
        ScheduledFuture<?> scheduledFuture = cache.get(key);
        if (scheduledFuture != null){
            scheduledFuture.cancel(true);
            cache.remove(key);
            log.info("当前key为{}的定时任务已取消",key);
        }

    }
}

工具类




@Component
public class SpringContextUtils implements ApplicationContextAware {
    private static ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextUtils.context = applicationContext;
    }

    public static Object getBean(String name){
        return context.getBean(name);
    }
}

方法测试


@Slf4j
@Component(value = "testTask")
public class TestTask {

    public void taskMethod(){
        log.info(String.format("调用了当前定时任务"));
    }
}


http://www.kler.cn/news/315277.html

相关文章:

  • 网传阿里云盘出现bug,可看到其他用户云盘图片
  • VideoFileClip 切割视频
  • C#往压缩包Zip文件的文件追加数据
  • go注册中心Eureka,注册到线上和线下,都可以访问
  • 通过示例来展示C++中Lumda函数的原理是什么及如何来使用它?
  • SOI 刻蚀气体
  • DHCP协议原理(网络协议)
  • 用apache httpd来实现反向代理
  • openFrameworks_如何使用ofxXmlSettings和ofxGui来创建识别界面
  • 机器人的动力学——牛顿欧拉,拉格朗日,凯恩
  • C++ —— vector 的模拟实现
  • 【计算机网络】运输层协议解析
  • Flutter - Win32程序是如何执行main函数
  • jmeter得到的文档数据处理
  • 后端接收数组,集合类数据
  • 数据结构之算法复杂度
  • 基于BiGRU+Attention实现风力涡轮机发电量多变量时序预测(PyTorch版)
  • 软考中级软件设计师——数据结构与算法基础学习笔记
  • 【图灵完备 Turing Complete】游戏经验攻略分享 Part.5 编程
  • 【若依RuoYi-Vue | 项目实战】帝可得后台管理系统(二)
  • Linux自主学习篇
  • oracle中NUMBER(1,0)的字段如何映射到c#中
  • 【设计模式-适配】
  • SSC377/D, 5M30 64/128MB, 1Tops1. 支持双摄,甚至三摄;2. 夜视全彩;3. 省内存、省带宽;4. 算力较大,适合新的算法模型;
  • 图像处理与分析
  • Spring的任务调度
  • 怎么在路由器上使用tcpdump抓包
  • Redisson 分布式锁的使用详解
  • Vue3中shallowRef和ref区别
  • 确保在AWS上的资源安全:构建坚不可摧的云安全防线