Spring 定时器schedule实现

注解方式:
核心类摘要:
1.ScheduledAnnotationBeanPostProcessor
2.ScheduledTaskRegistrar
3.TaskScheduler
4.ReschedulingRunnable
具体说明:
1.ScheduledAnnotationBeanPostProcessor

(1)核心方法:Object postProcessAfterInitialization(final Object bean, String beanName)
功能:负责@Schedule注解的扫描,构建ScheduleTask

(2)核心方法:onApplicationEvent(ContextRefreshedEvent event)
功能:spring容器加载完毕之后调用,ScheduleTask向ScheduledTaskRegistrar中注册, 调用ScheduledTaskRegistrar.afterPropertiesSet()

2.ScheduledTaskRegistrar

(1)核心方法:void afterPropertiesSet()
功能:初始化所有定时器,启动定时器

3.TaskScheduler
主要的实现类有三个 ThreadPoolTaskScheduler, ConcurrentTaskScheduler,TimerManagerTaskScheduler
作用:这些类的作用主要是将task和executor用ReschedulingRunnable包装起来进行生命周期管理。

(1)核心方法:ScheduledFuture schedule(Runnable task, Trigger trigger)

4.ReschedulingRunnable
(1)核心方法:public ScheduledFuture schedule()
(2)核心方法:public void run()

public ScheduledFuture schedule() {
        synchronized (this.triggerContextMonitor) {
            this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
            if (this.scheduledExecutionTime == null) {
                return null;
            }
            long initialDelay = this.scheduledExecutionTime.getTime() - System.currentTimeMillis();
            this.currentFuture = this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);
            return this;
        }
    }

    @Override
    public void run() {
        Date actualExecutionTime = new Date();
        super.run();
        Date completionTime = new Date();
        synchronized (this.triggerContextMonitor) {
            this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
        }
        if (!this.currentFuture.isCancelled()) {
            schedule();
        }
    }

通过schedule方法及run方法互相调用,再利用ScheduledExecutorService接口的schedule(Runnable command,long delay,TimeUnit unit)单次执行效果,从而实现一定时间重复触发的效果。

配置文件的方式基本相似只是通过ScheduledTasksBeanDefinitionParser类读取节点组装对应定时任务bean
Spring定时器的实现

ScheduledThreadPoolExecutor类

 public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
        if (command == null || unit == null)
            throw new NullPointerException();
        RunnableScheduledFuture<?> t = decorateTask(command, new ScheduledFutureTask<Void>(command, null, triggerTime(delay, unit)));
        delayedExecute(t);//延迟执行
        return t;
    }

    //执行到delaydExecute方法
    private void delayedExecute(RunnableScheduledFuture<?> task) {
        if (isShutdown())
            reject(task);
        else {
            super.getQueue().add(task);//把任务加入到执行队列中
            if (isShutdown() &&
                    !canRunInCurrentRunState(task.isPeriodic()) &&
                    remove(task))
                task.cancel(false);
            else
                ensurePrestart();//任务未取消则调用
        }
    }

任务未取消则调用ensurePrestart(),ensurePrestart方法中调用了addWorker()方法,addWorker()方法中创建执行任务的Woker并且调用woker的run方法,调用runWorker方法

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        while (task != null || (task = getTask()) != null) {
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if ((runStateAtLeast(ctl.get(), STOP) ||
                    (Thread.interrupted() &&
                            runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                wt.interrupt();
            try {
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x;
                    throw x;
                } catch (Error x) {
                    thrown = x;
                    throw x;
                } catch (Throwable x) {
                    thrown = x;
                    throw new Error(x);
                } finally {
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}

runWorker方法中的任务通过调用了ThreadPoolExecutor类中的getTask方法获得
getTask()方法中调用了ScheduledThreadPoolExecutor内部类DelayedWorkQueue重写的take方法或poll方法

public RunnableScheduledFuture<?> take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            //实现延迟执行,根据延迟时间等待直到执行时间返回RunnableScheduledFuture
            for (; ; ) {
                RunnableScheduledFuture<?> first = queue[0];
                if (first == null)
                    available.await();
                else {
                    long delay = first.getDelay(NANOSECONDS);
                    if (delay <= 0)
                        return finishPoll(first);
                    first = null; // don't retain ref while waiting
                    if (leader != null)
                        available.await();
                    else {
                        Thread thisThread = Thread.currentThread();
                        leader = thisThread;
                        try {
                            available.awaitNanos(delay);
                        } finally {
                            if (leader == thisThread)
                                leader = null;
                        }
                    }
                }
            }
        } finally {
            if (leader == null && queue[0] != null)
                available.signal();
            lock.unlock();
        }
    }

原文地址:https://www.cnblogs.com/baojiong/p/9444288.html

时间: 2024-10-24 16:08:45

Spring 定时器schedule实现的相关文章

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定时器中如何获取servletcontext

spring定时器中如何获取servletcontext 学习了:https://zhidao.baidu.com/question/406212574.html @Scheduled(cron = "0 0 */3 * * ?") // 3小时处理一次 public void updateData(){ System.out.println("*********************************schedule task"); WebApplicat

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错误笔记 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