Solon v2.7.5

Scheduled 调度(计划任务)

</> markdown

1、适配方案

两个方案,体验上总体差不多。一些细节上的差别,具体看插件的使用说明。

2、使用预览

启动类上,增加启用注解

// 启用 Scheduled 注解的任务
@EnableScheduling
public class JobApp {
    public static void main(String[] args) {
        Solon.start(JobApp.class, args);
    }
}

注解在类上

// 基于 Runnable 接口的模式
@Scheduled(fixedRate = 1000 * 3)
public class Job1 implements Runnable {
    @Override
    public void run() {
        System.out.println("我是 Job1 (3s)");
    }
}

增加拦截处理(如果有需要?),v2.7.2 后支持:

@Slf4j
@Component
public class JobInterceptorImpl implements JobInterceptor {
    @Override
    public void doIntercept(Job job, JobHandler handler) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            handler.handle(job.getContext());
        } catch (Throwable e) {
            //记录日志
            TagsMDC.tag0("job");
            TagsMDC.tag1(job.getName());
            log.error("{}", e);

            throw e; //别吃掉
        } finally {
            //记录一个内部处理的花费时间
            long timespan = System.currentTimeMillis() - start;
            System.out.println("JobInterceptor: job=" + job.getName());
        }
    }
}

3、注解 Scheduled 属性说明

属性说明备注
cron支持7位(秒,分,时,日期ofM,月,星期ofW,年)将并行执行
zone时区:+08 或 CET 或 Asia/Shanghai配合 cron 使用
fixedRate固定频率毫秒数(大于 0 时,cron 会失效)将并行执行
fixedDelay固定延时毫秒数(大于 0 时,cron 和 fixedRate 会失效)将串行执行
initialDelay初次执行延时毫秒数配合 fixedRate 或 fixedDelay 使用

不同的适配插件,支持程序略有不同。比如 quartz 不支持 fixedDelay 和 initialDelay(具体看相关插件页)。

4、内部管理接口 IJobManager

IJobManager 是内部管理接口,会在应用容器启动时启动,启动后状态会变成:isStarted() == true

public interface IJobManager extends Lifecycle {
    //任务添加(不需要再 jobStart)
    JobHolder jobAdd(String name, Scheduled scheduled, JobHandler handler);
    //任务是否存在
    boolean jobExists(String name);
    //任务获取
    JobHolder jobGet(String name);
    //任务移除(会自动停止)
    void jobRemove(String name);
    //任务开始(jobStop 后,才需要执行 jobStart 重新启动)
    void jobStart(String name, Map<String, String> data) throws ScheduledException;
    //任务停止
    void jobStop(String name) throws ScheduledException;
    //是否已启动
    boolean isStarted();
}

5、手动控制示例

//也可以被注入(注入,v2.5.6 后支持)
IJobManager jobManager = JobManager.getInstance();

//添加任务
if(jobManager.jobExists("demo") == false){
    jobManager.jobAdd("demo" , new ScheduledAnno().fixedRate(1000), (ctx)->{
       System.out.printl("Hello job");
    });
}

//移除任务
jobManager.jobRemove("demo");