package com.xiaoleilu.hutool.cron; import java.util.Map.Entry; import java.util.TimeZone; import java.util.UUID; import com.xiaoleilu.hutool.convert.Convert; import com.xiaoleilu.hutool.cron.listener.TaskListener; import com.xiaoleilu.hutool.cron.listener.TaskListenerManager; import com.xiaoleilu.hutool.cron.pattern.CronPattern; import com.xiaoleilu.hutool.cron.task.InvokeTask; import com.xiaoleilu.hutool.cron.task.RunnableTask; import com.xiaoleilu.hutool.cron.task.Task; import com.xiaoleilu.hutool.setting.Setting; import com.xiaoleilu.hutool.util.CollectionUtil; import com.xiaoleilu.hutool.util.ThreadUtil; /** * 任务调度器<br> * * 调度器启动流程:<br> * * <pre> * 启动Timer -> 启动TaskLauncher -> 启动TaskExecutor * </pre> * * 调度器关闭流程:<br> * * <pre> * 关闭Timer -> 关闭所有运行中的TaskLauncher -> 关闭所有运行中的TaskExecutor * </pre> * * 其中: * * <pre> * <strong>TaskLauncher</strong>:定时器每分钟调用一次(如果{@link Scheduler#isMatchSecond()}为<code>true</code>每秒调用一次), * 负责检查<strong>TaskTable</strong>是否有匹配到此时间运行的Task * </pre> * * <pre> * <strong>TaskExecutor</strong>:TaskLauncher匹配成功后,触发TaskExecutor执行具体的作业,执行完毕销毁 * </pre> * * @author Looly * */ public class Scheduler { private Object lock = new Object(); /** 时区 */ private TimeZone timezone; /** 是否已经启动 */ private boolean started = false; /** 是否支持秒匹配 */ protected boolean matchSecond = false; /** 是否支持年匹配 */ protected boolean matchYear = false; /** 是否为守护线程 */ protected boolean daemon; /** 定时器 */ private CronTimer timer; /** 定时任务表 */ protected TaskTable taskTable = new TaskTable(this); /** 启动器管理器 */ protected TaskLauncherManager taskLauncherManager; /** 执行器管理器 */ protected TaskExecutorManager taskExecutorManager; /** 监听管理器列表 */ protected TaskListenerManager listenerManager = new TaskListenerManager(); // --------------------------------------------------------- Getters and Setters start /** * 设置时区 * * @param timezone 时区 * @return this */ public Scheduler setTimeZone(TimeZone timezone) { this.timezone = timezone; return this; } /** * 获得时区,默认为 {@link TimeZone#getDefault()} * * @return 时区 */ public TimeZone getTimeZone() { return timezone != null ? timezone : TimeZone.getDefault(); } /** * 设置是否为守护线程<br> * 默认非守护线程 * * @param on <code>true</code>为守护线程,否则非守护线程 * @throws CronException */ public void setDaemon(boolean on) throws CronException { synchronized (lock) { if (started) { throw new CronException("Scheduler already started!"); } this.daemon = on; } } /** * 是否为守护线程 * @return 是否为守护线程 */ public boolean isDeamon(){ return this.daemon; } /** * 是否支持秒匹配 * @return <code>true</code>使用,<code>false</code>不使用 */ public boolean isMatchSecond(){ return this.matchSecond; } /** * 设置是否支持秒匹配,默认不使用 * @param isMatchSecond <code>true</code>支持,<code>false</code>不支持 * @return this */ public Scheduler setMatchSecond(boolean isMatchSecond) { this.matchSecond = isMatchSecond; return this; } /** * 是否支持年匹配 * @return <code>true</code>使用,<code>false</code>不使用 */ public boolean isMatchYear(){ return this.matchYear; } /** * 设置是否支持年匹配,默认不使用 * @param isMatchYear <code>true</code>支持,<code>false</code>不支持 * @return this */ public Scheduler setMatchYear(boolean isMatchYear) { this.matchYear = isMatchYear; return this; } /** * 增加监听器 * @param listener {@link TaskListener} * @return this */ public Scheduler addListener(TaskListener listener){ this.listenerManager.addListener(listener); return this; } /** * 移除监听器 * @param listener {@link TaskListener} * @return this */ public Scheduler removeListener(TaskListener listener){ this.listenerManager.removeListener(listener); return this; } // --------------------------------------------------------- Getters and Setters end // -------------------------------------------------------------------- shcedule start /** * 批量加入配置文件中的定时任务<br> * 配置文件格式为: * xxx.xxx.xxx.Class.method = * * * * * * @param cronSetting 定时任务设置文件 */ public Scheduler schedule(Setting cronSetting) { if(CollectionUtil.isNotEmpty(cronSetting)){ for (Entry<Object, Object> entry : cronSetting.entrySet()) { final String jobClass = Convert.toStr(entry.getKey()); final String pattern = Convert.toStr(entry.getValue()); try { schedule(pattern, new InvokeTask(jobClass)); } catch (Exception e) { throw new CronException(e, "Schedule [{}] [{}] error!", pattern, jobClass); } } } return this; } /** * 新增Task,使用随机UUID * * @param pattern {@link CronPattern}对应的String表达式 * @param task {@link Runnable} * @return ID */ public String schedule(String pattern, Runnable task) { return schedule(pattern, new RunnableTask(task)); } /** * 新增Task,使用随机UUID * * @param pattern {@link CronPattern}对应的String表达式 * @param task {@link Task} * @return ID */ public String schedule(String pattern, Task task) { String id = UUID.randomUUID().toString(); schedule(id, pattern, task); return id; } /** * 新增Task * * @param id ID,为每一个Task定义一个ID * @param pattern {@link CronPattern}对应的String表达式 * @param task {@link Runnable} * @return this */ public Scheduler schedule(String id, String pattern, Runnable task) { return schedule(id, new CronPattern(pattern), new RunnableTask(task)); } /** * 新增Task * * @param id ID,为每一个Task定义一个ID * @param pattern {@link CronPattern}对应的String表达式 * @param task {@link Task} * @return this */ public Scheduler schedule(String id, String pattern, Task task) { return schedule(id, new CronPattern(pattern), task); } /** * 新增Task * * @param id ID,为每一个Task定义一个ID * @param pattern {@link CronPattern} * @param task {@link Task} * @return this */ public Scheduler schedule(String id, CronPattern pattern, Task task) { taskTable.add(id, pattern, task); return this; } /** * 移除Task * * @param id Task的ID */ public synchronized void deschedule(String id) throws IndexOutOfBoundsException { this.taskTable.remove(id); } // -------------------------------------------------------------------- shcedule end /** * @return 是否已经启动 */ public boolean isStarted() { return this.started; } /** * 启动 * * @return this */ public Scheduler start() { synchronized (lock) { if (this.started) { throw new CronException("Schedule is started!"); } this.taskLauncherManager = new TaskLauncherManager(this); this.taskExecutorManager = new TaskExecutorManager(this); // Start CronTimer timer = new CronTimer(this); timer.setDaemon(this.daemon); timer.start(); this.started = true; } return this; } /** * 停止定时任务 * * @return this */ public Scheduler stop() { synchronized (lock) { if (!started) { throw new IllegalStateException("Scheduler not started"); } // 停止CronTimer ThreadUtil.interupt(this.timer, true); // 停止所有TaskLauncher taskLauncherManager.destroy(); // 停止所有TaskExecutor this.taskExecutorManager.destroy(); //修改标志 started = false; } return this; } // -------------------------------------------------------------------- notify start // -------------------------------------------------------------------- notify end }