Spring的業務層和Web層-----------任務排程
任務排程
quartz框架
quartz框架實現了Spring的任務排程,使用者可以隨意的定義觸發器排程時間表,並將觸發器和任務進行對映。quartz通過排程器、觸發器和任務實現任務排程。
Job:主要用來設計任務實現的邏輯,並且只有一個方法execute。
JobDetail:主要用來通過newInstance()方法建立Job例項,該角色主要通過一些靜態資訊來描述Job的名稱等資訊。
Triger:作為任務的觸發器,有兩個類:SimpleTriger和CronTriger。當只觸發一次或者週期性觸發選擇SimpleTriger。當定時觸發時可以選擇CronTriger。
Calendar:作為時間點的集合。
Scheduler:任務排程容器,Scheduler中註冊Triger和JobDetail,將Triger和JobDetail關聯起來。
實現任務排程步驟:
1、建立任務,並設定名稱和組名。2、建立觸發器,並設定名稱和組名。3、對觸發器設定時間規則。4、定義任務排程容器,將觸發器與任務加入容器,並這隻關聯。
SimpleTriger任務排程例項:
建立任務類
package scheduler; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class SimpleJob implements Job{ @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { // TODO Auto-generated method stub System.out.println("定時任務排程================="); } }
將任務與觸發器關聯
/** * */ /** * @author Administrator * */ package scheduler; import java.util.Collection; import org.quartz.Job; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.SimpleTrigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; import sun.java2d.pipe.SpanShapeRenderer.Simple; public class SimpleTriggerRunner { public static void main(String[] args){ try{ JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).withIdentity("job_1", "group_1").build(); SimpleTrigger trigger = TriggerBuilder .newTrigger() .withIdentity("trigger_1","group_triger") .startNow() .withSchedule(SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(5) .repeatForever()) .build(); SchedulerFactory factory = new StdSchedulerFactory(); Scheduler scheduler = factory.getScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); }catch(Exception e){ e.printStackTrace(); } } }
CronTriger實現任務排程例項:
import java.util.Collection; import org.quartz.Job; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.SimpleTrigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; import sun.java2d.pipe.SpanShapeRenderer.Simple; public class SimpleTriggerRunner { public static void main(String[] args){ try{ JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).withIdentity("job_1", "group_1").build(); SimpleTrigger trigger = TriggerBuilder .newTrigger() .withIdentity("trigger_1","group_triger") .startNow() .withSchedule(SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(5) .repeatForever()) .build(); SchedulerFactory factory = new StdSchedulerFactory(); Scheduler scheduler = factory.getScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); }catch(Exception e){ e.printStackTrace(); } } }
Spring中使用quartz
建立JobDetailBean
步驟:
1、建立JobDetail例項JobDetailBean。對JobDetailBean進行屬性設定,jobClass:用來指定任務;beanName:設定任務的名稱;JobDataAsMap為任務的JobDataMap提供值;applicationContextJobDataKey:為Job提供applicationContext。2、建立Trigger觸發器,主要是通過SimpleTriggerBean、CronTriggerBean和CronTriggerFactoryBean進行建立,需要將任務例項配置其中。3、通過SchedulerFactoryBean類配置Scheduler,將Trigger加入Schedulerde的Trigger列表中。
例項:
定義任務類
package scheduler; import java.util.Map; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.stereotype.Component; import bean.User; @Component("myJob") public class MyJob{ public void myexecute() { // TODO Auto-generated method stub System.out.println("Spring開始任務排程========="); System.out.println("Spring結束任務排程=========="); } }
將任務加入觸發器,並設定排程時間。將觸發器加入排程。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" 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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd" > <context:component-scan base-package="scheduler"/> <!-- jobDetail --> <bean id="jobnew" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="myJob"/> <property name="targetMethod" value="myexecute"/> <!--false表示等上一個任務執行完後再開啟新的任務--> <property name="concurrent" value="false"/> </bean> <!-- Trigger--> <bean id="oceanStatusCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="jobnew"/> <property name="cronExpression" value="0 */2 * * * ?"/> </bean> <!--Scheduler --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="oceanStatusCronTrigger"/> </list> </property> </bean> </beans>
Spring中使用Timer
Timer
當使用排程比較頻繁時,可以考慮使用Timer,並不適合固定時間點例如每週週一上午八點的排程策略。但是對於長時間執行的任務來說,該排程會嚴重影響效能,因為每一個Timer是在同一個執行緒,Timer中的有多個TimerTask,執行時間過長容易引起積壓。
TmierTask
TimerTask相當於Job,TimerTask實現了Runnable介面,該類中主要有三個方法:任務執行邏輯,執行時間,取消執行。
實現任務排程的步驟:
1、建立TimerTask類。2、建立Timer類。3、將TimerTask例項註冊到Timer中。
例項
建立任務例項
package scheduler; import java.util.TimerTask; public class SimpleTimerTask extends TimerTask{ private int count=0; @Override public void run() { // TODO Auto-generated method stub System.out.println("執行緒執行次數========="+count); count++; if(count>10){ cancel(); } } }
將任務註冊到Timer中
package scheduler; import java.util.Timer; import java.util.TimerTask; public class TimerRunner { public static void main(String[] args){ Timer timer = new Timer(); TimerTask timerTask = new SimpleTimerTask(); timer.schedule(timerTask, 1000, 2000); } }
Spring對Timer的使用
建立任務類
package scheduler; import org.springframework.stereotype.Component; @Component("myService") public class MyService { public void timerTest(){ System.out.println("開始使用TimerTask========="); } }
將任務類封裝為TimerTask,並將TimerTask設定定時規則,將規則注入Timer。
<!-- 通過生成任務TimerTask --> <bean id="timerTask" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean" p:targetObject-ref="myService" p:targetMethod="timerTest"/> <!-- 定義排程規則 --> <bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask" p:timerTask-ref="timerTask" p:delay="1000" p:period="1000"/> <!-- 將排程規則放入排程佇列 --> <bean id="timerFactoryBean" class="org.springframework.scheduling.timer.TimerFactoryBean"> <property name="scheduledTimerTasks"> <list> <ref bean="scheduledTask"/> </list> </property> </bean>
Spring中使用Executor
Executor主要有兩個任務:任務提交和任務執行。Executor只有一個方法:void execute(Runnable command),該方法接收任何實現了Runnable的例項。
Executor的簡單實現:
package scheduler; import java.util.concurrent.Executor; public class SimpleExecutor implements Executor{ @Override public void execute(Runnable command) { // TODO Auto-generated method stub command.run(); } }
可以為每個任務建立一個執行緒:
package scheduler; import java.util.concurrent.Executor; public class TaskExecutor implements Executor{ @Override public void execute(Runnable command) { // TODO Auto-generated method stub //為每一個任務重新建立一個執行緒 new Thread(command).start(); } }
可以將任務放到執行緒池排程中,每一個任務會通過獲取執行緒,進行任務處理。SchedulerThreadPoolExecutor繼承ThreadPoolExecutor,ThreadPoolExecutor繼承了Executor和ExecutorService。而SchedulerThreadPoolExecutor通過newFixedThreadPool(int nThreads)建立一個執行緒池進行任務處理。
使用例項:
package scheduler; public class SimpleRunnable implements Runnable{ @Override public void run() { // TODO Auto-generated method stub System.out.println("開啟任務執行=========="); } }
package scheduler; import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class ExecutorExample { private Executor executor; public void setExecutor(Executor executor){ this.executor = executor; } public void executeTask(){ for(int i=0;i<6;i++){ executor.execute(new SimpleRunnable()); } } public static void main(String args){ ExecutorExample ee = new ExecutorExample(); ee.setExecutor(Executors.newFixedThreadPool(3)); ee.executeTask(); } }
Spring任務排程的註解支援
@Schedule的例項
配置定時任務:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" 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-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/util http://www.springframework.org/schema/util/spring-util-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"> <context:component-scan base-package="scheduler"/> <!-- 啟用註解驅動的定時任務 --> <task:annotation-driven scheduler="myScheduler"/> <!-- 推薦配置執行緒池,若不配置多工下會有問題。後面會詳細說明單執行緒的問題。 --> <task:scheduler id="myScheduler" pool-size="5"/> </beans>
建立任務類
package scheduler; import java.util.Map; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.stereotype.Component; import bean.User; @Component("myJob") public class MyJob{ public void myexecute() { // TODO Auto-generated method stub System.out.println("Spring開始任務排程========="); System.out.println("Spring結束任務排程=========="); } }