ThreadPoolTaskScheduler手寫任務調度

先貼一個自己寫的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();
    }

}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章