Java动态定时任务

基于上一篇动态多定时任务,想到貌似可以将其扩展一下,于是有了这篇。
上一篇链接

完整代码:

实体类:

Java 复制代码
@Data
public class DemoTask {

    private String id;
    //0 fixed 1 cron
    private int type;

    //fixed required
    private int seconds;
    //cron required
    private String cron;

    private String methodName;

    private String input;
}

核心处理类:

Java 复制代码
@Slf4j
@Component
public class DemoTaskService {

    @Autowired
    private TaskScheduler taskScheduler;
    @Autowired
    private ApplicationContext applicationContext;

    private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();

    /**
     * 启动定时任务
     */
    public void startTask(DemoTask task) {
        stopTask(task.getId()); // 先停止现有任务

        ScheduledFuture<?> scheduledFuture = null;
        if (task.getType() == 0) {
            int seconds = task.getSeconds();
            if(seconds <= 0) {
                seconds = 30;
            }
            //ThreadPoolTaskScheduler
            scheduledFuture = taskScheduler.scheduleAtFixedRate(
                    () -> executeTask(task),
                    Duration.ofSeconds(seconds)
            );
        } else {
            String cron = task.getCron();
            scheduledFuture = taskScheduler.schedule(
                    () -> executeTask(task),
                    new CronTrigger(cron)
            );
        }
        log.info("要启动的任务: {}", task.getId());
        futureMap.put(task.getId(), scheduledFuture);
    }

    // 停止任务
    public void stopTask(String areaId) {
        log.info("要停止的任务id: {}", areaId);
        if (futureMap.containsKey(areaId)) {
            log.info("任务存在,即将停止: {}", areaId);
            futureMap.get(areaId).cancel(true);
            futureMap.remove(areaId);
        }
    }

    private void executeTask(DemoTask task) {
        log.info("execute task: {}, taskType: {}, methodName: {}", task.getId(), task.getType(), task.getMethodName());
        try {
            String[] split = task.getMethodName().split("#");
            String className = split[0];
            String methodName = split[1];
            Class<?> aClass = Class.forName(className);
            Object bean = applicationContext.getBean(aClass);

            MethodInvoker invoker = new MethodInvoker();
            invoker.setTargetObject(bean);
            invoker.setTargetMethod(methodName);
            invoker.setArguments(task.getInput());
            invoker.prepare();
            invoker.invoke();
        } catch (Exception e) {
            log.error("executeTask出现错误", e);
        }
    }
}

测试

接口:

Java 复制代码
@RestController
public class TestController {

    @Autowired
    private DemoTaskService demoTaskService;

    @PostMapping("startTask")
    public String startTask(@RequestBody DemoTask task) {
        demoTaskService.startTask(task);
        return "ok start " + task.getId();
    }

    @GetMapping
    public String stopTask(@PathVariable String taskId) {
        demoTaskService.stopTask(taskId);
        return "ok stop " + taskId;
    }
}

任务:

Java 复制代码
@Slf4j
@Component
public class DemoTestTask {

    public void test1(String input) {
        log.info("start test1 input: {}", input);
    }

    public void test2(String input) {
        log.info("start test2 input: {}", input);
    }
}

参数:

复制代码
{
    "id": 111111,
    "type": 0,
    "seconds": 10,
    "cron": "*/20 * * * * ?",
    "input": "hahaha",
    "methodName": "com.example.demo.runner.DemoTestTask#test1"
}

{
    "id": 222222,
    "type": 1,
    "seconds": 10,
    "cron": "*/20 * * * * ?",
    "input": "hehehe",
    "methodName": "com.example.demo.runner.DemoTestTask#test2"
}

效果:

复制代码
2026-05-16T15:49:27.518+08:00  INFO 15640 --- [demo] [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-05-16T15:49:27.518+08:00  INFO 15640 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2026-05-16T15:49:27.518+08:00  INFO 15640 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
2026-05-16T15:49:27.658+08:00  INFO 15640 --- [demo] [nio-8080-exec-1] c.example.demo.service.DemoTaskService   : 要停止的任务id: 111111
2026-05-16T15:49:27.658+08:00  INFO 15640 --- [demo] [nio-8080-exec-1] c.example.demo.service.DemoTaskService   : 要启动的任务: 111111
2026-05-16T15:49:27.658+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 111111, taskType: 0, methodName: com.example.demo.runner.DemoTestTask#test1
2026-05-16T15:49:27.658+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test1 input: hahaha
2026-05-16T15:49:37.666+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 111111, taskType: 0, methodName: com.example.demo.runner.DemoTestTask#test1
2026-05-16T15:49:37.666+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test1 input: hahaha
2026-05-16T15:49:44.446+08:00  INFO 15640 --- [demo] [nio-8080-exec-3] c.example.demo.service.DemoTaskService   : 要停止的任务id: 222222
2026-05-16T15:49:44.461+08:00  INFO 15640 --- [demo] [nio-8080-exec-3] c.example.demo.service.DemoTaskService   : 要启动的任务: 222222
2026-05-16T15:49:47.667+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 111111, taskType: 0, methodName: com.example.demo.runner.DemoTestTask#test1
2026-05-16T15:49:47.667+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test1 input: hahaha
2026-05-16T15:49:57.666+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 111111, taskType: 0, methodName: com.example.demo.runner.DemoTestTask#test1
2026-05-16T15:49:57.666+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test1 input: hahaha
2026-05-16T15:50:00.011+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 222222, taskType: 1, methodName: com.example.demo.runner.DemoTestTask#test2
2026-05-16T15:50:00.011+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test2 input: hehehe
2026-05-16T15:50:07.676+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 111111, taskType: 0, methodName: com.example.demo.runner.DemoTestTask#test1
2026-05-16T15:50:07.676+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test1 input: hahaha
2026-05-16T15:50:17.665+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 111111, taskType: 0, methodName: com.example.demo.runner.DemoTestTask#test1
2026-05-16T15:50:17.665+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test1 input: hahaha
2026-05-16T15:50:20.009+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 222222, taskType: 1, methodName: com.example.demo.runner.DemoTestTask#test2
2026-05-16T15:50:20.009+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test2 input: hehehe
2026-05-16T15:50:27.668+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 111111, taskType: 0, methodName: com.example.demo.runner.DemoTestTask#test1
2026-05-16T15:50:27.668+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test1 input: hahaha
2026-05-16T15:50:37.669+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 111111, taskType: 0, methodName: com.example.demo.runner.DemoTestTask#test1
2026-05-16T15:50:37.669+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test1 input: hahaha
2026-05-16T15:50:40.012+08:00  INFO 15640 --- [demo] [   scheduling-1] c.example.demo.service.DemoTaskService   : execute task: 222222, taskType: 1, methodName: com.example.demo.runner.DemoTestTask#test2
2026-05-16T15:50:40.012+08:00  INFO 15640 --- [demo] [   scheduling-1] com.example.demo.runner.DemoTestTask     : start test2 input: hehehe

上面的日志可以看到,111111和222222这两个定时任务,调接口启动后,这两个任务确实按10秒和20秒的定时在跑了

相关推荐
ZhengEnCi11 小时前
J7A-高级Java工程师面试三道灵魂拷问-深度广度与工程素养的终极检验
java·后端
狼爷1 天前
吃透 Java Function 接口,搞定 99% 的 Stream 场景
java·函数式编程
祎雪双十Gy1 天前
从 DataX 的配置加载说起:我用 FastJson2 做了一个轻量级动态配置管理库
java·后端
小锋java12341 天前
分享一套锋哥原创的SpringBoot4+Vue3宠物领养网站系统
java
考虑考虑2 天前
Java实现hmacsha1加密算法
java·后端·java ee
掉鱼的猫2 天前
Spring Boot → Solon 注解迁移实战指南:一张对照表说清楚
java·spring boot
plainGeekDev2 天前
广播接收器 → Flow + Lifecycle
android·java·kotlin
plainGeekDev2 天前
EventBus → SharedFlow
android·java·kotlin
带刺的坐椅2 天前
Spring Boot → Solon 注解迁移实战指南:一张对照表说清楚
java·springboot·web·solon
用户3721574261352 天前
Java 将一个 PPT 文档拆分为多个文件
java