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秒的定时在跑了

相关推荐
创可贴治愈心灵几秒前
AI浪潮下C#就业前景剖析:深耕C#为主,按需选修Java与Python
java·人工智能·c#
huohaiyu15 分钟前
深入解析Java垃圾回收机制
java·开发语言·算法·gc
SunnyDays101129 分钟前
如何在 Java 中实现 OFD 与 PDF 格式互转
java·开发语言
小江的记录本1 小时前
【Spring全家桶】Spring Cloud 2023.0.x:微服务核心理论、CAP/BASE定理(附《思维导图》+《面试高频考点清单》)
java·spring boot·后端·spring·spring cloud·微服务·面试
Solis程序员1 小时前
缓存三剑客预防策略
java·spring·缓存
我登哥MVP2 小时前
Spring Boot 从“会用”到“精通”:Model-Map原理
java·spring boot·后端·spring·servlet·maven·mybatis
程序猿乐锅2 小时前
【苍穹外卖|Day02】后台接口自测闭环:Token、DTO 与 yml 配置
java·开发语言
心之伊始2 小时前
Spring Boot Actuator + Micrometer 自定义业务指标:不只是健康检查
java·架构·源码分析·csdn
Eason_LYC2 小时前
【GetShell 实战】CVE-2026-34486 Tomcat 加密拦截器绕过:从漏洞验证到反弹 Shell 全流程
java·渗透测试·tomcat·java反序列化·rce·远程代码执行漏洞·cve-2026-34486