先貼一個自己寫的demo把,原理其實就是這樣的。
先記錄一個東西,後續來研究:CronSequenceGenerator
報錯:Cron expression must consist of 6 fields,這玩意支持6位不支持7位,真是XXXX,quartz支持,參見 https://my.oschina.net/uwith/blog/4395339 。
CronTrigger這個類可以將cron表達式轉換成Date,可以查看schedule源碼學到不少東西,下面代碼就是轉換成下一執行時間。
public Date nextExecutionTime(TriggerContext triggerContext)
@Slf4j @RestController public class HomeController { /** * 存儲調度器信息,存在多線程安全問題,採用ConcurrentHashMap * 初始大小設定大於核心線程池數量3倍即可 */ private Map<Integer, ScheduledFuture> map = new ConcurrentHashMap<>(64); ThreadPoolTaskScheduler threadPoolTaskScheduler; public HomeController() { // 注意,此線程池使用DelayedWorkQueue()作爲隊列,此隊列又是基於PriorityQueue, // 自己會根據表達式進行排序,可以查看schedule方法源碼以及參數 threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); threadPoolTaskScheduler.initialize(); // 線程池需做配置化 threadPoolTaskScheduler.setPoolSize(64); } @RequestMapping("/home/index/{id}") public String add(@PathVariable Integer id, @RequestBody String cron) { // 添加一個去重複的操作 if (map.containsKey(id)) { return "調度任務已添加成功"; } ScheduledFuture future = threadPoolTaskScheduler.schedule( new Runnable() { @Override public void run() { try { // 觸發進行記錄日誌 StopWatch watch = new StopWatch(); watch.start(); log.info(String.format("%s-調度器已觸發,準備rpc調用", id)); // 這裏執行具體的操作 Thread.sleep(1000); //執行完成取消 Boolean cancelResult = cancel(id); watch.stop(); log.info(String.format("%s-調度器rpc調用完成,耗時:%s", id, watch.getLastTaskTimeMillis())); } catch (Exception ex) { log.error(String.format("%s-調度器出現異常:%s,堆棧信息:%s", id, ex.getMessage(), ExceptionUtils.getStackTrace(ex))); } } }, new CronTrigger(cron)); // 暫時緩存,用於控制 map.put(id, future); return "調度任務已添加成功"; } @RequestMapping("/home/cancel/{id}") public Boolean cancel(@PathVariable Integer id) { ScheduledFuture future = map.get(id); // mayInterruptIfRunning參數指明是否可以中斷線程, // 注意如果寫true那麼該段代碼執行完成,後續操作可能會被中斷,比如下面的remove方法,可能執行不到 Boolean result = future.cancel(true); // 然後移除緩存 map.remove(id); return Boolean.TRUE; } @RequestMapping("/home/query/{id}") public String query(@PathVariable Integer id) { ScheduledFuture future = map.get(id); StringBuilder sb = new StringBuilder(); sb.append(String.format("future.isCancelled:%s</br>", future.isCancelled())); sb.append(String.format("future.isDone:%s</br>", future.isDone())); return sb.toString(); } @RequestMapping("/home/queryInfo") public String queryInfo() { StringBuilder sb = new StringBuilder(); sb.append(String.format("getPoolSize:%s</br>", threadPoolTaskScheduler.getPoolSize())); sb.append(String.format("getActiveCount:%s</br>", threadPoolTaskScheduler.getActiveCount())); sb.append(String.format("getScheduledExecutor.isShutdown", threadPoolTaskScheduler.getScheduledExecutor().isShutdown())); sb.append(String.format("getScheduledExecutor.isTerminated:%s</br>", threadPoolTaskScheduler.getScheduledExecutor().isTerminated())); sb.append(String.format("getScheduledThreadPoolExecutor.getPoolSize:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getPoolSize())); sb.append(String.format("getScheduledThreadPoolExecutor.getCorePoolSize:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getCorePoolSize())); sb.append(String.format("getScheduledThreadPoolExecutor.getLargestPoolSize:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getLargestPoolSize())); sb.append(String.format("getScheduledThreadPoolExecutor.getMaximumPoolSize:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getMaximumPoolSize())); sb.append(String.format("getScheduledThreadPoolExecutor.getActiveCount:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getActiveCount())); sb.append(String.format("getScheduledThreadPoolExecutor.getTaskCount:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getTaskCount())); sb.append(String.format("getScheduledThreadPoolExecutor.getCompletedTaskCount:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getCompletedTaskCount())); sb.append(String.format("getScheduledThreadPoolExecutor.getQueue:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getQueue().size())); sb.append(String.format("getScheduledThreadPoolExecutor.getKeepAliveTime:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().getKeepAliveTime(TimeUnit.SECONDS))); sb.append(String.format("getScheduledThreadPoolExecutor.isShutdown:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().isShutdown())); sb.append(String.format("getScheduledThreadPoolExecutor.isTerminating:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().isTerminating())); sb.append(String.format("getScheduledThreadPoolExecutor.isTerminated:%s</br>", threadPoolTaskScheduler.getScheduledThreadPoolExecutor().isTerminated())); return sb.toString(); } }