1. 程式人生 > >自定義spring定時器

自定義spring定時器

() spl public == integer service upd imei second

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

}

自定義spring定時器