change cron

This commit is contained in:
Looly
2020-10-31 20:57:22 +08:00
parent 6674dcbde7
commit 905a4da3ee
12 changed files with 216 additions and 49 deletions

View File

@@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
# 5.4.7 (2020-10-29)
# 5.4.7 (2020-10-31)
### 新特性
* 【core 】 增加OptionalBeanpr#1182@Github
@@ -13,10 +13,12 @@
* 【http 】 增加SoapClient增加addSOAPHeader重载
* 【http 】 ArrayUtil增加containsAll方法
* 【http 】 增加CharsetDetector
* 【cron 】 增加CronTask监听支持获取idissue#I23315@Gitee
### Bug修复
* 【core 】 修复BeanUtil.beanToMap方法中editor返回null没有去掉的问题
* 【core 】 修复ImgUtil.toBufferedImage颜色模式的问题issue#1194@Github
* 【cron 】 修复TimeZone设置无效的问题issue#I23315@Gitee
-------------------------------------------------------------------------------------------------------------

View 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;
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)));
}
}
}
}
}

View File

@@ -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);
}
}
}

View 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;
}
}

View File

@@ -10,6 +10,7 @@ package cn.hutool.cron.task;
*
* @author Looly
*/
@FunctionalInterface
public interface Task {
/**

View File

@@ -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"));