最近项目中用到了定时任务,以前没有接触过,在此对java中定时任务的实现进行总结。
实现定时任务的方式有2种,一种是使用java类库中的java.util.Timer;另一种是使用quartz框架。
Timer只能实现简单的任务调度,quartz可以满足各种复杂的任务调度时间需求。
1、Timer的实现方式
在Timer中存在一个任务(Task)的概念,通过继承java.util.TimerTask实现,代码如下:
Java代码 <span style="font-size: 14px;">public class MyTask extends TimerTask{ @Override public void run() { System.out.println("execute my task!"); } }</span>
然后使用Timer实例实现任务的触发和调度,代码如下:
Java代码 <span style="font-size: 14px;">public class MyTimer { public static void main(String[] args) { Timer timer= new Timer(); // 1秒钟后开始第一次,以后每隔2秒执行一次 timer.schedule(new MyTask(), 1000, 2000); } }</span>
Timer的定时任务实现就这么简单。
原理:
1)通过源码可知Timer使用队列(TaskQueue)和线程(TimerThread)实现任务的调度;
2)使用Wait-Notify机制实现队列的阻塞操作;
2、quartz实现方式
Quartz 是个开源的作业调度框架,为java应用程序的作业调度提供了简单却强大的机制。
在quartz中存在一下几个概念:
1)job,相当于timer的task;
2)Trigger(触发器),用来执行job
3)Scheduler(调度器),用来管理Trigger
下面是一个简单例子:
Java代码 <span style="font-size: 14px;">public class SimpleJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { //获取jobDetail JobDetail jobDetail = context.getJobDetail(); // 获取jobName String jobName = jobDetail.getName(); //获取JobDataMap JobDataMap dataMap = jobDetail.getJobDataMap(); //JobDataMap中获取用户传入的参数 int index = dataMap.getInt("index"); //具体JOB要做的事 for(int i =0;i<index;i++){ try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { } System.out.println("simple job name:"+jobName+" ;turn "+i); } } }</span>
Java代码 <span style="font-size: 14px;">public class QuartzTest { public static void main(String[] args) { try { // 1、创建一个任务调度器 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); //2、创建一个作业 JobDetail jobDetail = new JobDetail("simpleJob", Scheduler.DEFAULT_GROUP, SimpleJob.class); // 2.1、JobDataMap里面加入需要的参数 jobDetail.getJobDataMap().put("index", 5); //3、创建触发器,每8秒触发一次 Trigger trigger = TriggerUtils.makeSecondlyTrigger(8); trigger.setName("simpleTrigger"); //3.1、开始触发时间 trigger.setStartTime(new Date()); // 4、把作业和触发器 scheduler.scheduleJob(jobDetail, trigger); // 5、启动调度器 scheduler.start(); // 6、关闭调度器 scheduler.shutdown(); } catch (SchedulerException se) { se.printStackTrace(); } } }</span>
其中JobExecutionContext是quartz提供的一个上下文,从中可以获取job、trigger的信息;
quartz还有许多其他特性,例如job持久化、properties配置文件等,详细可参考最后的链接。
3、spring实现方式
spring对Java的Timer类和Quartz都提供了一个抽象层,使用我们可以更方便地使用它们。
1)spring对Timer的集成
Xml代码 <span style="font-size: 14px;"><?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" default-autowire="byName"> <bean id="timer" class="org.springframework.scheduling.timer.TimerFactoryBean"> <property name="scheduledTimerTasks"> <list> <ref local="schedule" /> </list> </property> </bean> <bean id="schedule" class="org.springframework.scheduling.timer.ScheduledTimerTask"> <property name="timerTask"> <ref bean="myTask" /> </property> <property name="delay"> <value>1000</value> </property> <property name="period"> <value>1000</value> </property> </bean> <bean id="myTask" class="com.test.MyTask" /> </beans></span>
2)spring对quartz的集成
Java代码 <span style="font-size: 14px;"><?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" default-autowire="byName"> <bean id="myTask" class="com.test.MyTask" /> <!-- jobDetail --> <bean id="quartzJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="myTask" /> <property name="targetMethod" value="run" /> <property name="concurrent" value="false" /> </bean> <!-- trigger --> <bean id="quartzTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="quartzJobDetail" /> <property name="cronExpression" value="0/3 * * * * ?"/> </bean> <!-- schdule --> <bean id="quertzSchdule" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="quartzTrigger" /> </list> </property> </bean> </beans></span>
在spring容器加载配置文件中的bean后,任务调度就会开始。
