史上最全最详细的Spring定时任务的讲解以及实例

来源:互联网 发布:织梦cms 地区分站 编辑:程序博客网 时间:2024/05/22 00:54

一、最原始的定时任务

1.采用线程方式

public static void runTask(){        final long timeInterval = 1000;        Runnable runnable = new Runnable() {            public void run() {                while (true){                    System.out.println("hello");                    try {                        Thread.sleep(timeInterval);                    }catch (InterruptedException e){                        e.printStackTrace();                    }                }            }        };        Thread thread = new Thread(runnable);        thread.start();    }

二、采用jdk中的Timer类

package com.flx.timer;import com.flx.timer.task.SimpleTask;import com.flx.timer.task.SimpleTaskLiving;import com.flx.util.BaseFunction;import com.flx.util.date.CalendarUtils;import java.util.Date;import java.util.Timer;import java.util.TimerTask;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;/** * Created by Fenglixiong on 2017/9/25. */public class TimerHome {    private static Timer timer = new Timer();    public static void main(String[] args) {        TaskOne(10);        TaskTwo(CalendarUtils.addSeconds(new Date(),10));        TaskThree(CalendarUtils.addSeconds(new Date(),10));        TaskFour();        TaskFive(CalendarUtils.addSeconds(new Date(),10));        TaskSix();        TimerTaskPool();        TimerTask01();        TimerTask02();    }    /**     * 指定延迟时间执行定时任务     * @param time     */    public static void TaskOne(int time){        BaseFunction.console("准备执行任务TaskOne...");        Timer timer = new Timer();        timer.schedule(new SimpleTask(),time*1000);    }    /**     * 在指定时间执行任务     * @param date     */    public static void TaskTwo(Date date){        BaseFunction.console("准备执行任务TaskTwo...");        CalendarUtils.sayTime(new Date());        Timer timer = new Timer();        timer.schedule(new SimpleTask(),date);    }    /**     * 在指定时间执行然后以指定时间间隔执行任务     * @param date     */    public static void TaskThree(Date date){        BaseFunction.console("准备执行任务TaskThree...");        CalendarUtils.sayTime(new Date());        Timer timer = new Timer();        timer.schedule(new SimpleTaskLiving("TaskThree"),date,3000);    }    /**     * 在指定时间延迟之后执行然后以指定时间间隔执行任务     *     */    public static void TaskFour(){        BaseFunction.console("准备执行任务TaskFour...");        CalendarUtils.sayTime(new Date());        Timer timer = new Timer();        timer.schedule(new SimpleTaskLiving("TaskFour"),5000,3000);    }    /**     * 在指定时间延迟之后执行然后以指定时间间隔执行任务     *     */    public static void TaskFive(Date firstTime){        BaseFunction.console("准备执行任务TaskFive...");        CalendarUtils.sayTime(new Date());        Timer timer = new Timer("TaskFive");        timer.scheduleAtFixedRate(new SimpleTaskLiving(),firstTime,3000);    }    /**     * 在指定时间延迟之后执行然后以指定时间间隔执行任务     *     */    public static void TaskSix(){        BaseFunction.console("准备执行任务TaskSix...");        CalendarUtils.sayTime(new Date());        Timer timer = new Timer();        timer.scheduleAtFixedRate(new SimpleTaskLiving("TaskSix"),20000,3000);    }    /**     * TimerTask01();     * TimerTask02();     * 同时执行这两个task     * 1.如果是两个Timer的话相当于两个线程互相不会影响     * 2.如果是一个Timer的话计划执行两个定时任务的话     *      其中一个延迟或者阻塞会影响另一个任务的执行     */    public static void TimerTask01(){        CalendarUtils.sayTime(new Date());        timer.schedule(new TimerTask() {            public void run() {                System.out.println("start:TimerTask01");                try {                    BaseFunction.console("运行:--->TimerTask01");                    Thread.sleep(15000);    //线程休眠3000                    BaseFunction.console("休眠后--->TimerTask01");                    CalendarUtils.sayTime(new Date());//                    throw new RuntimeException();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }, 1000);    }    public static void TimerTask02(){        CalendarUtils.sayTime(new Date());        timer.schedule(new TimerTask() {            public void run() {                System.out.println("运行:TimerTask02");                CalendarUtils.sayTime(new Date());//                throw new RuntimeException("...");            }        }, 5000);    }    /**     * ScheduledExecutorService是从Java SE5的java.util.concurrent里,     * 做为并发工具类被引进的,这是最理想的定时任务实现方式。     */    public static void TimerTaskPool(){        Runnable runnable = new Runnable() {            public void run() {                // task to run goes here                System.out.println("Hello !!");            }        };        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();        executorService.scheduleAtFixedRate(runnable,10,1, TimeUnit.SECONDS);    }}/** schedule(TimerTask task, Date time):安排在指定的时间执行指定的任务。 schedule(TimerTask task, Date firstTime, long period) :安排指定的任务在指定的时间开始进行重复的固定延迟执行。 schedule(TimerTask task, long delay) :安排在指定延迟后执行指定的任务。 schedule(TimerTask task, long delay, long period) :安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。 同时也重载了scheduleAtFixedRate方法,scheduleAtFixedRate方法与schedule相同,只不过他们的侧重点不同,区别后面分析。 scheduleAtFixedRate(TimerTask task, Date firstTime, long period):安排指定的任务在指定的时间开始进行重复的固定速率执行。 scheduleAtFixedRate(TimerTask task, long delay, long period):安排指定的任务在指定的延迟后开始进行重复的固定速率执行。 *//** * TimerTask TimerTask类是一个抽象类,由Timer 安排为一次执行或重复执行的任务。它有一个抽象方法run()方法, 该方法用于执行相应计时器任务要执行的操作。因此每一个具体的任务类都必须继承TimerTask,然后重写run()方法。 另外它还有两个非抽象的方法: boolean cancel():取消此计时器任务。 long scheduledExecutionTime():返回此任务最近实际执行的安排执行时间。 */

三、Spring自身集成的Task任务

(1)配置文件方式

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">    <!--此任务写到注解执行了-->    <!--<task:scheduled-tasks>-->        <!--<task:scheduled ref="simpleTaskJob" method="jobOne" cron="0/2 * * * * ?"/>-->    <!--</task:scheduled-tasks>-->        <!--新闻抓取-->    <task:scheduled-tasks>        <task:scheduled ref="simpleTaskService" method="sayHello" cron="0/2 * * * * ?" fixed-delay="1000"/>    </task:scheduled-tasks>    <!--债券抓取-->    <task:scheduled-tasks>        <task:scheduled ref="simpleTaskService" method="sayGood" cron="0/5 * * * * ?" />    </task:scheduled-tasks>    <!--上证E互动-->    <task:scheduled-tasks>        <task:scheduled ref="simpleTaskService" method="sayLove" cron="0/10 * * * * ?" />    </task:scheduled-tasks>    <!--公告-->    <task:scheduled-tasks>        <task:scheduled ref="simpleTaskService" method="sayNo" cron="0/15 * * * * ?" />    </task:scheduled-tasks>    <!--港交所股票持有数抓取-->    <task:scheduled-tasks>        <task:scheduled ref="simpleTaskService" method="sayYes" cron="0/20 * * * * ?" />    </task:scheduled-tasks></beans><!--字段   允许值   允许的特殊字符秒    0-59    , - * /分    0-59    , - * /小时    0-23    , - * /日期    1-31    , - * ? / L W C月份    1-12 或者 JAN-DEC    , - * /星期    1-7 或者 SUN-SAT    , - * ? / L C #年(可选)    留空, 1970-2099    , - * /- 区间* 通配符? 你不想设置那个字段下面只例出几个式子CRON表达式    含义"0 0 12 * * ?"    每天中午十二点触发"0 15 10 ? * *"    每天早上10:15触发"0 15 10 * * ?"    每天早上10:15触发"0 15 10 * * ? *"    每天早上10:15触发"0 15 10 * * ? 2005"    2005年的每天早上10:15触发"0 * 14 * * ?"    每天从下午2点开始到2点59分每分钟一次触发"0 0/5 14 * * ?"    每天从下午2点开始到2:55分结束每5分钟一次触发"0 0/5 14,18 * * ?"    每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发"0 0-5 14 * * ?"    每天14:00至14:05每分钟一次触发"0 10,44 14 ? 3 WED"    三月的每周三的14:10和14:44触发"0 15 10 ? * MON-FRI"    每个周一、周二、周三、周四、周五的10:15触发-->


(2)注解方式

首先要开启注解驱动

<task:annotation-driven scheduler="poolScheduler" mode="proxy"/><task:scheduler id="poolScheduler" pool-size="10"/>

任务类

@Servicepublic class SimpleTaskJob {    private int count = 0;    /**     * ApplicationContext.xml中配置了注解驱动之后完美执行任务     * 下面解除注释就可以执行     */    @Scheduled(cron = "0/2 * * * * ?")    public void jobOne() {        System.out.println("jobOne任务中....."+(++count));    }}


四、Spring结合Quartz实现精确定时任务

(1)最标准的写法

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">    <!--1.增加线程池,用于任务注册-->    <bean id="poolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">        <property name="corePoolSize" value="10"/>        <property name="maxPoolSize" value="20"/>        <property name="queueCapacity" value="500"/>    </bean>    <!--2.定义业务逻辑处理类-->    <bean id="simpleTask" class="com.flx.quartz.schedule.SimpleTask"/>    <!--3.增加调度业务逻辑-->    <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">        <property name="targetObject" ref="simpleTask"/>        <property name="targetMethod" value="doTask"/>    </bean>    <!--4.增加调度触发器-->    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">        <property name="jobDetail" ref="jobDetail"/>        <property name="startDelay" value="3000"/>        <property name="repeatInterval" value="2000"/>    </bean>    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">        <property name="jobDetail" ref="jobDetail"/>        <property name="cronExpression" value="0/3 * * * * ?"/>    </bean>    <!--5.增加调度-->    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">        <property name="triggers">            <list>                <ref bean="simpleTrigger"/>                <ref bean="cronTrigger"/>            </list>        </property>        <property name="taskExecutor" ref="poolTaskExecutor"/>    </bean></beans>

(2)复杂的Quartz调用

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task"       xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">    <!--定时器数据,可选-->    <bean id="message" class="com.flx.app.entity.Message">        <property name="status" value="100"/>        <property name="message" value="very good"/>    </bean>    <bean id="methodTask" class="com.flx.quartz.schedule.MethodTask"/><!--Job任务类start-->    <!-- For times when you just need to invoke a method on a specific object -->    <bean id="simpleTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">        <property name="targetObject" ref="methodTask"/>        <property name="targetMethod" value="sayHello"/>    </bean>    <bean id="firstComplexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">        <property name="jobClass" value="com.flx.quartz.schedule.FirstComplexJobDetail"/>        <property name="jobDataMap">            <map>                <entry key="message" value-ref="message"/>            </map>        </property>        <!--即使trigger不关联也不会被删除-->        <property name="durability" value="true"/>    </bean>    <bean id="secondComplexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">        <property name="jobClass" value="com.flx.quartz.schedule.SecondComplexJobDetail"/>        <property name="durability" value="true"/>    </bean>    <!--如果你需要更高级的设置,需要给作业传递数据,想更加灵活的话就使用这种方式。-->    <bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">        <property name="jobClass" value="com.flx.quartz.schedule.SimpleQuartzJob"/>        <property name="jobDataMap">            <map>                <entry key="message" value-ref="message"/>            </map>        </property>        <!--如果一个任务不是durable,那么当没有Trigger关联它的时候,它就会被自动删除。-->        <property name="durability" value="true"/>        <property name="description" value="简单的作业实现"/>    </bean><!--Job任务类end--><!--A简单触发器-->    <!--配置 Quartz 调度时要使用到的触发器-->    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">        <property name="jobDetail" ref="simpleTask"/>        <property name="startDelay" value="3000"/>        <property name="repeatInterval" value="2000"/>        <property name="repeatCount" value="4"/>        <!--<property name="startTime" value=""/>-->    </bean><!--B计划触发器-->    <!--这种类型更加灵活,允许你针对特定实例选择计划方案以及将来要执行的频率。-->    <bean id="firstCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">        <property name="jobDetail" ref="firstComplexJobDetail"/>        <property name="cronExpression" value="0/5 * * ? * *"/>    </bean>    <bean id="secondCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">        <property name="jobDetail" ref="secondComplexJobDetail"/>        <property name="cronExpression" value="0/10 * * ? * *"/>    </bean><!--将任务和计划全部整合在以前-->    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">        <property name="triggers">            <list>                <ref bean="simpleTrigger"/>                <ref bean="firstCronTrigger"/>                <ref bean="secondCronTrigger"/>            </list>        </property>    </bean></beans>

最后开启测试类

public static void main(String[] args) {        AbstractApplicationContext context = new ClassPathXmlApplicationContext("timer/spring-quartz-task.xml");        AbstractApplicationContext context = new ClassPathXmlApplicationContext("timer/simple-quartz-task.xml");    }





原创粉丝点击