您的位置:首页 > 编程语言 > Java开发

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

2017-09-29 13:46 701 查看
一、最原始的定时任务

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"/>


任务类

@Service
public 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/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://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="me
ab2c
ssage" 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");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: