diff --git a/CHANGELOG.md b/CHANGELOG.md index 3164988b1..247415636 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.4.7 (2020-10-29) +# 5.4.7 (2020-10-31) ### 新特性 * 【core 】 增加OptionalBean(pr#1182@Github) @@ -13,10 +13,12 @@ * 【http 】 增加SoapClient增加addSOAPHeader重载 * 【http 】 ArrayUtil增加containsAll方法 * 【http 】 增加CharsetDetector +* 【cron 】 增加CronTask,监听支持获取id(issue#I23315@Gitee) ### Bug修复 * 【core 】 修复BeanUtil.beanToMap方法中editor返回null没有去掉的问题 * 【core 】 修复ImgUtil.toBufferedImage颜色模式的问题(issue#1194@Github) +* 【cron 】 修复TimeZone设置无效的问题(issue#I23315@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-cron/src/main/java/cn/hutool/cron/CronConfig.java b/hutool-cron/src/main/java/cn/hutool/cron/CronConfig.java new file mode 100644 index 000000000..cbb3a7713 --- /dev/null +++ b/hutool-cron/src/main/java/cn/hutool/cron/CronConfig.java @@ -0,0 +1,64 @@ +package cn.hutool.cron; + +import java.util.TimeZone; + +/** + * 定时任务配置类 + * + * @author looly + * @since 5.4.7 + */ +public class CronConfig { + + /** + * 时区 + */ + protected TimeZone timezone = TimeZone.getDefault(); + /** + * 是否支持秒匹配 + */ + protected boolean matchSecond; + + public CronConfig(){ + } + + /** + * 设置时区 + * + * @param timezone 时区 + * @return this + */ + public CronConfig setTimeZone(TimeZone timezone) { + this.timezone = timezone; + return this; + } + + /** + * 获得时区,默认为 {@link TimeZone#getDefault()} + * + * @return 时区 + */ + public TimeZone getTimeZone() { + return this.timezone; + } + + /** + * 是否支持秒匹配 + * + * @return true使用,false不使用 + */ + public boolean isMatchSecond() { + return this.matchSecond; + } + + /** + * 设置是否支持秒匹配,默认不使用 + * + * @param isMatchSecond true支持,false不支持 + * @return this + */ + public CronConfig setMatchSecond(boolean isMatchSecond) { + this.matchSecond = isMatchSecond; + return this; + } +} diff --git a/hutool-cron/src/main/java/cn/hutool/cron/CronTimer.java b/hutool-cron/src/main/java/cn/hutool/cron/CronTimer.java index abc95544c..d25c92add 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/CronTimer.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/CronTimer.java @@ -37,7 +37,7 @@ public class CronTimer extends Thread implements Serializable { @Override public void run() { - final long timerUnit = this.scheduler.matchSecond ? TIMER_UNIT_SECOND : TIMER_UNIT_MINUTE; + final long timerUnit = this.scheduler.config.matchSecond ? TIMER_UNIT_SECOND : TIMER_UNIT_MINUTE; long thisTime = System.currentTimeMillis(); long nextTime; diff --git a/hutool-cron/src/main/java/cn/hutool/cron/Scheduler.java b/hutool-cron/src/main/java/cn/hutool/cron/Scheduler.java index b9a925800..ed0e78d33 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/Scheduler.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/Scheduler.java @@ -57,19 +57,17 @@ public class Scheduler implements Serializable { private final Lock lock = new ReentrantLock(); - /** 时区 */ - private TimeZone timezone; + /** 定时任务配置 */ + protected CronConfig config = new CronConfig(); /** 是否已经启动 */ private boolean started = false; - /** 是否支持秒匹配 */ - protected boolean matchSecond = false; /** 是否为守护线程 */ protected boolean daemon; /** 定时器 */ private CronTimer timer; /** 定时任务表 */ - protected TaskTable taskTable = new TaskTable(this); + protected TaskTable taskTable = new TaskTable(); /** 启动器管理器 */ protected TaskLauncherManager taskLauncherManager; /** 执行器管理器 */ @@ -83,11 +81,11 @@ public class Scheduler implements Serializable { /** * 设置时区 * - * @param timezone 时区 + * @param timeZone 时区 * @return this */ - public Scheduler setTimeZone(TimeZone timezone) { - this.timezone = timezone; + public Scheduler setTimeZone(TimeZone timeZone) { + this.config.setTimeZone(timeZone); return this; } @@ -97,7 +95,7 @@ public class Scheduler implements Serializable { * @return 时区 */ public TimeZone getTimeZone() { - return timezone != null ? timezone : TimeZone.getDefault(); + return this.config.getTimeZone(); } /** @@ -136,7 +134,7 @@ public class Scheduler implements Serializable { * @return true使用,false不使用 */ public boolean isMatchSecond() { - return this.matchSecond; + return this.config.isMatchSecond(); } /** @@ -146,7 +144,7 @@ public class Scheduler implements Serializable { * @return this */ public Scheduler setMatchSecond(boolean isMatchSecond) { - this.matchSecond = isMatchSecond; + this.config.setMatchSecond(isMatchSecond); return this; } @@ -347,7 +345,7 @@ public class Scheduler implements Serializable { * @since 4.1.17 */ public Scheduler clear() { - this.taskTable = new TaskTable(this); + this.taskTable = new TaskTable(); return this; } // -------------------------------------------------------------------- shcedule end diff --git a/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutor.java b/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutor.java index 5365751f0..f74a4f15f 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutor.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutor.java @@ -1,5 +1,6 @@ package cn.hutool.cron; +import cn.hutool.cron.task.CronTask; import cn.hutool.cron.task.Task; /** @@ -12,15 +13,25 @@ import cn.hutool.cron.task.Task; public class TaskExecutor implements Runnable { private final Scheduler scheduler; - private final Task task; + private final CronTask task; /** - * 获得任务对象 + * 获得原始任务对象 * * @return 任务对象 */ public Task getTask() { - return task; + return this.task.getRaw(); + } + + /** + * 获得原始任务对象 + * + * @return 任务对象 + * @since 5.4.7 + */ + public CronTask getCronTask() { + return this.task; } /** @@ -29,7 +40,7 @@ public class TaskExecutor implements Runnable { * @param scheduler 调度器 * @param task 被执行的任务 */ - public TaskExecutor(Scheduler scheduler, Task task) { + public TaskExecutor(Scheduler scheduler, CronTask task) { this.scheduler = scheduler; this.task = task; } diff --git a/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutorManager.java b/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutorManager.java index c3d1308a6..09a06eb2a 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutorManager.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/TaskExecutorManager.java @@ -1,12 +1,13 @@ package cn.hutool.cron; +import cn.hutool.cron.task.CronTask; +import cn.hutool.cron.task.Task; + import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import cn.hutool.cron.task.Task; - /** * 作业执行管理器
* 负责管理作业的启动、停止等 @@ -47,7 +48,7 @@ public class TaskExecutorManager implements Serializable { * @param task {@link Task} * @return {@link TaskExecutor} */ - public TaskExecutor spawnExecutor(Task task) { + public TaskExecutor spawnExecutor(CronTask task) { final TaskExecutor executor = new TaskExecutor(this.scheduler, task); synchronized (this.executors) { this.executors.add(executor); diff --git a/hutool-cron/src/main/java/cn/hutool/cron/TaskLauncher.java b/hutool-cron/src/main/java/cn/hutool/cron/TaskLauncher.java index 675ae8576..5b85c277f 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/TaskLauncher.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/TaskLauncher.java @@ -12,7 +12,13 @@ public class TaskLauncher implements Runnable{ private final Scheduler scheduler; private final long millis; - + + /** + * 构造 + * + * @param scheduler {@link Scheduler} + * @param millis 毫秒数 + */ public TaskLauncher(Scheduler scheduler, long millis) { this.scheduler = scheduler; this.millis = millis; @@ -21,7 +27,7 @@ public class TaskLauncher implements Runnable{ @Override public void run() { //匹配秒部分由用户定义决定,始终不匹配年 - scheduler.taskTable.executeTaskIfMatchInternal(millis); + scheduler.taskTable.executeTaskIfMatch(this.scheduler, this.millis); //结束通知 scheduler.taskLauncherManager.notifyLauncherCompleted(this); diff --git a/hutool-cron/src/main/java/cn/hutool/cron/TaskTable.java b/hutool-cron/src/main/java/cn/hutool/cron/TaskTable.java index 27daf2948..517db1ebd 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/TaskTable.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/TaskTable.java @@ -1,13 +1,13 @@ package cn.hutool.cron; import cn.hutool.cron.pattern.CronPattern; +import cn.hutool.cron.task.CronTask; import cn.hutool.cron.task.Task; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.TimeZone; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -22,24 +22,33 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; public class TaskTable implements Serializable { private static final long serialVersionUID = 1L; - private final ReadWriteLock lock = new ReentrantReadWriteLock(); + public static final int DEFAULT_CAPACITY = 10; - private final Scheduler scheduler; - private final TimeZone timezone; + private final ReadWriteLock lock; - private final List ids = new ArrayList<>(); - private final List patterns = new ArrayList<>(); - private final List tasks = new ArrayList<>(); + private final List ids; + private final List patterns; + private final List tasks; private int size; /** * 构造 - * - * @param scheduler {@link Scheduler} */ - public TaskTable(Scheduler scheduler) { - this.scheduler = scheduler; - this.timezone = scheduler.getTimeZone(); + public TaskTable() { + this(DEFAULT_CAPACITY); + } + + /** + * 构造 + * + * @param initialCapacity 容量,即预估的最大任务数 + */ + public TaskTable(int initialCapacity) { + lock = new ReentrantReadWriteLock(); + + ids = new ArrayList<>(initialCapacity); + patterns = new ArrayList<>(initialCapacity); + tasks = new ArrayList<>(initialCapacity); } /** @@ -246,13 +255,14 @@ public class TaskTable implements Serializable { /** * 如果时间匹配则执行相应的Task,带读锁 * + * @param scheduler {@link Scheduler} * @param millis 时间毫秒 */ - public void executeTaskIfMatch(long millis) { + public void executeTaskIfMatch(Scheduler scheduler, long millis) { final Lock readLock = lock.readLock(); readLock.lock(); try { - executeTaskIfMatchInternal(millis); + executeTaskIfMatchInternal(scheduler, millis); } finally { readLock.unlock(); } @@ -261,14 +271,15 @@ public class TaskTable implements Serializable { /** * 如果时间匹配则执行相应的Task,无锁 * + * @param scheduler {@link Scheduler} * @param millis 时间毫秒 * @since 3.1.1 */ - protected void executeTaskIfMatchInternal(long millis) { + protected void executeTaskIfMatchInternal(Scheduler scheduler, long millis) { for (int i = 0; i < size; i++) { - if (patterns.get(i).match(timezone, millis, this.scheduler.matchSecond)) { - this.scheduler.taskExecutorManager.spawnExecutor(tasks.get(i)); + if (patterns.get(i).match(scheduler.config.timezone, millis, scheduler.config.matchSecond)) { + scheduler.taskExecutorManager.spawnExecutor(new CronTask(ids.get(i), patterns.get(i), tasks.get(i))); } } } -} +} \ No newline at end of file diff --git a/hutool-cron/src/main/java/cn/hutool/cron/listener/TaskListenerManager.java b/hutool-cron/src/main/java/cn/hutool/cron/listener/TaskListenerManager.java index ff2f5502c..e326f9472 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/listener/TaskListenerManager.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/listener/TaskListenerManager.java @@ -65,8 +65,8 @@ public class TaskListenerManager implements Serializable { public void notifyTaskSucceeded(TaskExecutor executor) { synchronized (listeners) { int size = listeners.size(); - for (TaskListener listenerl : listeners) { - listenerl.onSucceeded(executor); + for (TaskListener listener : listeners) { + listener.onSucceeded(executor); } } } diff --git a/hutool-cron/src/main/java/cn/hutool/cron/task/CronTask.java b/hutool-cron/src/main/java/cn/hutool/cron/task/CronTask.java new file mode 100644 index 000000000..c3442a378 --- /dev/null +++ b/hutool-cron/src/main/java/cn/hutool/cron/task/CronTask.java @@ -0,0 +1,70 @@ +package cn.hutool.cron.task; + +import cn.hutool.cron.pattern.CronPattern; + +/** + * 定时作业,此类除了定义了作业,也定义了作业的执行周期以及ID。 + * + * @author looly + * @since 5.4.7 + */ +public class CronTask implements Task{ + + private final String id; + private CronPattern pattern; + private final Task task; + + /** + * 构造 + * @param id ID + * @param pattern 表达式 + * @param task 作业 + */ + public CronTask(String id, CronPattern pattern, Task task) { + this.id = id; + this.pattern = pattern; + this.task = task; + } + + @Override + public void execute() { + task.execute(); + } + + /** + * 获取作业ID + * + * @return 作业ID + */ + public String getId() { + return id; + } + + /** + * 获取表达式 + * + * @return 表达式 + */ + public CronPattern getPattern() { + return pattern; + } + + /** + * 设置新的定时表达式 + * @param pattern 表达式 + * @return this + */ + public CronTask setPattern(CronPattern pattern){ + this.pattern = pattern; + return this; + } + + /** + * 获取原始作业 + * + * @return 作业 + */ + public Task getRaw(){ + return this.task; + } +} diff --git a/hutool-cron/src/main/java/cn/hutool/cron/task/Task.java b/hutool-cron/src/main/java/cn/hutool/cron/task/Task.java index 1db81a88f..ca2b77deb 100644 --- a/hutool-cron/src/main/java/cn/hutool/cron/task/Task.java +++ b/hutool-cron/src/main/java/cn/hutool/cron/task/Task.java @@ -10,6 +10,7 @@ package cn.hutool.cron.task; * * @author Looly */ +@FunctionalInterface public interface Task { /** diff --git a/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java b/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java index 569e54cd4..33e94f552 100644 --- a/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java +++ b/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java @@ -22,6 +22,9 @@ public class CronTest { // 支持秒级别定时任务 CronUtil.setMatchSecond(true); CronUtil.start(); + + ThreadUtil.waitForDie(); + Console.log("Exit."); } @Test @@ -32,27 +35,27 @@ public class CronTest { CronUtil.getScheduler().setDaemon(false); CronUtil.start(); - ThreadUtil.sleep(3000); + ThreadUtil.waitForDie(); CronUtil.stop(); } @Test @Ignore - public void cronTest2() { + public void cronWithListenerTest() { CronUtil.getScheduler().addListener(new TaskListener() { @Override public void onStart(TaskExecutor executor) { - Console.log("Listen task start!"); + Console.log("Found task:[{}] start!", executor.getCronTask().getId()); } @Override public void onSucceeded(TaskExecutor executor) { - + Console.log("Found task:[{}] success!", executor.getCronTask().getId()); } @Override public void onFailed(TaskExecutor executor, Throwable exception) { - + Console.error("Found task:[{}] failed!", executor.getCronTask().getId()); } }); @@ -65,7 +68,7 @@ public class CronTest { } @Test -// @Ignore + @Ignore public void addAndRemoveTest() { String id = CronUtil.schedule("*/2 * * * * *", (Runnable) () -> Console.log("task running : 2s"));