zoukankan      html  css  js  c++  java
  • 自定义spring定时器

    package com.wjz.quartz;
    
    import java.util.concurrent.Executors;
    
    public class QuartzDemo {
        
        public static void main(String[] args) throws Exception {
            
            new MyRunnable(Executors.newSingleThreadScheduledExecutor()).schedule();
            // 这里让main线程睡眠是因为如果主线程执行完了MyRunnable对象就被销毁了实验效果无法展现
            Thread.sleep(1000*60*5);
            
        }
    }

    我可以看到初始化了一个任务线程延迟调度器ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();注入到了Runnable中

    核心类MyRunnable实现了Runnable和ScheduledFuture接口

    run方法中执行了任务调度

    package com.wjz.quartz;
    
    import java.util.Date;
    import java.util.concurrent.Delayed;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.ScheduledFuture;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.TimeoutException;
    
    import org.springframework.scheduling.support.SimpleTriggerContext;
    
    class MyRunnable implements Runnable, ScheduledFuture<Object> {
        
        private final ScheduledExecutorService executor;
        private final MyTrigger trigger = new MyTrigger();
        private final SimpleTriggerContext triggerContext = new SimpleTriggerContext();
        private final Object triggerContextMonitor = new Object();
        private ScheduledFuture<?> currentFuture;
        private Date scheduledExecutionTime;
        
        public MyRunnable(ScheduledExecutorService executor) {
            this.executor = executor;
        }
        
        public ScheduledFuture<?> schedule() {
            synchronized (triggerContextMonitor) {
            // 获得计划中的下一个执行时间
    this.scheduledExecutionTime = trigger.nextExecutionTime(triggerContext); long delay = scheduledExecutionTime.getTime() - System.currentTimeMillis();
            // 延时任务调度
    this.currentFuture = executor.schedule(this, delay, TimeUnit.MILLISECONDS); return this; } } public void run() { Date actualExecutionTime = new Date(); System.out.println("------调用定时方法------"); Date completionTime = new Date(); synchronized (triggerContextMonitor) { triggerContext.update(scheduledExecutionTime, actualExecutionTime, completionTime); if (!this.currentFuture.isCancelled()) { schedule(); } } } public boolean cancel(boolean mayInterruptIfRunning) { synchronized (this.triggerContextMonitor) { return this.currentFuture.cancel(mayInterruptIfRunning); } } public boolean isCancelled() { synchronized (this.triggerContextMonitor) { return this.currentFuture.isCancelled(); } } public boolean isDone() { synchronized (this.triggerContextMonitor) { return this.currentFuture.isDone(); } } public Object get() throws InterruptedException, ExecutionException { ScheduledFuture<?> curr; synchronized (this.triggerContextMonitor) { curr = this.currentFuture; } return curr.get(); } public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { ScheduledFuture<?> curr; synchronized (this.triggerContextMonitor) { curr = this.currentFuture; } return curr.get(timeout, unit); } public long getDelay(TimeUnit unit) { ScheduledFuture<?> curr; synchronized (this.triggerContextMonitor) { curr = this.currentFuture; } return curr.getDelay(unit); } public int compareTo(Delayed other) { if (this == other) { return 0; } long diff = getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS); return (diff == 0 ? 0 : ((diff < 0)? -1 : 1)); } }

    触发器主要是返回触发时间

    package com.wjz.quartz;
    
    import java.util.Date;
    
    import org.springframework.scheduling.Trigger;
    import org.springframework.scheduling.TriggerContext;
    
    public class MyTrigger implements Trigger {
        
        private MySequence sequence = new MySequence();
        
        public Date nextExecutionTime(TriggerContext triggerContext) {
            Date date = triggerContext.lastCompletionTime();
            if (date == null) {
                date = new Date();
            }
            return sequence.next(date);
        }
    
    }

    计划时间表生成器主要是生成触发时间和返回下一个触发时间

    package com.wjz.quartz;
    
    import java.util.BitSet;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.GregorianCalendar;
    import java.util.TimeZone;
    
    public class MySequence {
        
        private final BitSet seconds = new BitSet(60);
        
        MySequence() {
            setNumber(seconds, "0/5", 0, 60);
        }
    
        public Date next(Date date) {
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(date);
            calendar.setTimeZone(TimeZone.getDefault());
            // 重置毫秒数
            calendar.set(Calendar.MILLISECOND, 0);
            long originalTimestamp = calendar.getTimeInMillis();
            doNext(calendar);
            if (calendar.getTimeInMillis() == originalTimestamp) {
                // 日历时间刚好到了原始时间戳时间,加一秒
                calendar.add(Calendar.SECOND, 1);
                doNext(calendar);
            }
            return calendar.getTime();
        }
    
        private void doNext(Calendar calendar) {
            int second = calendar.get(Calendar.SECOND);
            int nextSecond = seconds.nextSetBit(second);
            if (nextSecond == -1) {
                // 加一分钟
                calendar.add(Calendar.MINUTE, 1);
                // 重置秒数
                calendar.set(Calendar.SECOND, 0);
                nextSecond = seconds.nextSetBit(0);
            }
            if (second != nextSecond) {
                calendar.set(Calendar.SECOND, nextSecond);
            }
        }
        
        private static void setNumber(BitSet bitSet, String field, int min, int max) {
            String[] fields = field.split("/"); // 0, 5
            int[] split = new int[2];
            int start = split[0] = Integer.valueOf(fields[0]);
            int grow = split[1] = Integer.valueOf(fields[1]);
            int[] range = new int[2];
            range[0] = split[0];
            int end = range[1] = max - 1;
            for (int i = start; i < end; i += grow) {
                bitSet.set(i);
            }
        }
    
    }
  • 相关阅读:
    Java经典编程题50道之四十一
    Java经典编程题50道之四十
    Java经典编程题50道之三十九
    Java经典编程题50道之三十八
    Java经典编程题50道之三十七
    Java经典编程题50道之三十六
    Java经典编程题50道之三十五
    前端学习之路之CSS (一)
    Numpy 01
    Python3 urllib 与 Python2 urllib的变化
  • 原文地址:https://www.cnblogs.com/BINGJJFLY/p/7495070.html
Copyright © 2011-2022 走看看