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

}
时间: 2024-10-07 15:41:32

自定义spring定时器的相关文章

spring定时器

本人小菜鸟一枚,今天在公司看到一段spring定时器配置,自己总结一下! <!-- 定义调用对象和调用对象的方法 --><bean id="jobtask9" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><!-- 调用的类 --><property name="targetObject"&

Spring 定时器的使用

spring定时器应用 相关类: org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean 配置定时远行方法 org.springframework.scheduling.quartz.CronTriggerBean 配置定时调度时间 org.springframework.scheduling.quartz.SchedulerFactoryBean 调度总控 MyEclipse自动生成项目,导入spring

[spring-framework]Spring定时器的配置和使用

开发中我们常常会做一些定时任务,这些任务有开始时间,并会按一定的周期或规则执行.如此我们在Java程序开发中使用定时器来处理定时任务. <!-- MessageRequestTask类中包含了msgRequest方法,用于执行定时任务 --> <bean id="msg_request" class="com.santorini.task.timer.MessageRequestTask"></bean> <!-- 定时器配

Spring定时器的配置和使用

开发中我们常常会做一些定时任务,这些任务有开始时间,并会按一定的周期或规则执行.如此我们在Java程序开发中使用定时器来处理定时任务. <!-- MessageRequestTask类中包含了msgRequest方法,用于执行定时任务 --> <bean id="msg_request" class="com.santorini.task.timer.MessageRequestTask"></bean> <!-- 定时器配

Spring定时器的配置

Spring定时器的配置(注解+xml)方式 (2013-09-30 10:39:18)转载▼ 标签: spring定时器配置 spring定时器注解方式 spring定时器xml方式 spring配置 分类: Spring Spring 配置定时器(注解+xml)方式—整理 一.注解方式 1. 在Spring的配置文件ApplicationContext.xml,首先添加命名空间 xmlns:task="http://www.springframework.org/schema/task&qu

spring 定时器执行两次

spring错误笔记 spring定时器执行两次因为导入了两次 关于配置文件如下 <bean id="timeTaskService" class="xx.xxx.xxx.xxx.service.impl.na.TimeTaskService"/> <task:scheduled-tasks scheduler="myScheduler"><!--30秒执行一次 --> <task:scheduled r

Spring定时器技术终结者——采用Scheduled注释的方式实现Spring定时器

在Spring中有两种方式可以实现定时器的功能,分别是Scheduled注释方式和XML配置方式,本博客将介绍如何在Spring中使用Scheduled注释方式的方式实现定时器的功能,代码及相应的解释如下: 代码1-Spring配置文件(applicationContext.xml文件): <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframe

Spring定时器配置的两种实现方式OpenSymphony Quartz和java Timer详解

原创整理不易,转载请注明出处:Spring定时器配置的两种实现方式OpenSymphony Quartz和java Timer详解 代码下载地址:http://www.zuidaima.com/share/1772648445103104.htm 有两种流行Spring定时器配置:Java的Timer类和OpenSymphony的Quartz. 1.Java Timer定时 首先继承java.util.TimerTask类实现run方法 import java.util.TimerTask; p

一个简单的Spring定时器例子 注解方式

首先在applicationContext.xml中增加 文件头中增加一条 xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation 中增加一条 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd <beans xmlns:task=&quo