浏览代码

change cron

Looly 5 年之前
父节点
当前提交
905a4da3ee

+ 3 - 1
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)
 
 -------------------------------------------------------------------------------------------------------------
 

+ 64 - 0
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 <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;
+	}
+}

+ 1 - 1
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;

+ 10 - 12
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 <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

+ 15 - 4
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;
 	}

+ 4 - 3
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;
-
 /**
  * 作业执行管理器<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);

+ 8 - 2
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);

+ 28 - 17
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<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;
 
 	/**
 	 * 构造
+	 */
+	public TaskTable() {
+		this(DEFAULT_CAPACITY);
+	}
+
+	/**
+	 * 构造
 	 *
-	 * @param scheduler {@link Scheduler}
+	 * @param initialCapacity 容量,即预估的最大任务数
 	 */
-	public TaskTable(Scheduler scheduler) {
-		this.scheduler = scheduler;
-		this.timezone = scheduler.getTimeZone();
+	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)));
 			}
 		}
 	}
-}
+}

+ 2 - 2
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);
 			}
 		}
 	}

+ 70 - 0
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;
+	}
+}

+ 1 - 0
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 {
 
 	/**

+ 9 - 6
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"));