自定义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);
        }
    }

}

 

posted @ 2017-09-08 15:56  BINGJJFLY  阅读(1422)  评论(0编辑  收藏  举报