mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
change cron
This commit is contained in:
@@ -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)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
64
hutool-cron/src/main/java/cn/hutool/cron/CronConfig.java
Normal file
64
hutool-cron/src/main/java/cn/hutool/cron/CronConfig.java
Normal file
@@ -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 <code>true</code>使用,<code>false</code>不使用
|
||||
*/
|
||||
public boolean isMatchSecond() {
|
||||
return this.matchSecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否支持秒匹配,默认不使用
|
||||
*
|
||||
* @param isMatchSecond <code>true</code>支持,<code>false</code>不支持
|
||||
* @return this
|
||||
*/
|
||||
public CronConfig setMatchSecond(boolean isMatchSecond) {
|
||||
this.matchSecond = isMatchSecond;
|
||||
return this;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
@@ -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 <code>true</code>使用,<code>false</code>不使用
|
||||
*/
|
||||
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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
/**
|
||||
* 作业执行管理器<br>
|
||||
* 负责管理作业的启动、停止等
|
||||
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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<String> ids = new ArrayList<>();
|
||||
private final List<CronPattern> patterns = new ArrayList<>();
|
||||
private final List<Task> tasks = new ArrayList<>();
|
||||
private final List<String> ids;
|
||||
private final List<CronPattern> patterns;
|
||||
private final List<Task> 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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
70
hutool-cron/src/main/java/cn/hutool/cron/task/CronTask.java
Normal file
70
hutool-cron/src/main/java/cn/hutool/cron/task/CronTask.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
@@ -10,6 +10,7 @@ package cn.hutool.cron.task;
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Task {
|
||||
|
||||
/**
|
||||
|
@@ -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"));
|
||||
|
||||
|
Reference in New Issue
Block a user