每當我們想在項目中定期去執行或者重複執行某一個操作,定時這個字眼總會自覺不自覺的浮現在腦海裏。當我們並不熟悉任何定時器的時候,我們可能會選擇使用線程來完成這個工作:
<span style="font-size:18px;">package org.ysc.action
public class FinanceAction extends Thread{
private Date date;
public void run{
try{
while(true){
Thread.sleep((int)(Math.random()*1000));
date = new Date();
//定時執行任務
}
}catch(Exception e){
e.printStackTrace();
}
}
}</span>
但是如果我們的定時器實現不好,將會使定時器佔用系統中的過多內存,給系統造成性能問題,所以在執行定時或者重複的任務,線程並不是最好的選擇;
java中常用的定時器
1).使用java.util.Timer 來實現
2).Quartz這個開源的調度框架
➷ Timer的具體實現
使用Timer定義一個定時任務主要分爲兩個步驟:
1. 創建定時任務類:
<span style="font-size:18px;">package org.ysc.action import java.util.TimeTask public class MyTimeTask extends TimeTask{ public void run(){ //要執行的定時任務 } }</span>
2. 運行定時任務:
2.1 程序直接啓動
<span style="font-size:18px;">package org.ysc.action public class Testmain{ ....... public void run(){ //執行定時器的任務 //創建實例 Timer timer = new Timer(); 參數: new MyTimeTask()- 所要安排的任務。 0- 執行任務前的延遲時間,單位是毫秒。 1*1000- 執行各後續任務之間的時間間隔,單位是毫秒。 timer.schedule(new MyTimeTask(),0,1*1000); } }</span>
2.2 web監聽的方式web.xml的配置
具體實現代碼:<span style="font-size:18px;"><listener> <listener-class> org.ysc.action.Testmain </listener-class> </listener></span>
<span style="font-size:18px;">package org.ysc.action public class Testmain implements ServletContextListener{ private Timer timer = null; //初始化監聽器,創建實例,執行任務 public void contextInitialized(ServletContextEvent event){ timer = new Timer(); timer.schedule(new MyTimeTask(),0,1*1000); } //銷燬監聽器,停止執行任務 public void contextDestroyed(ServletContextEvent event){ //注意,在此計時器調用的計時器任務的 run 方法內調用此方法,就可以絕對確保正在執行的任務是此計時器所執行的最後一個任務。 timer.cancel(); } }</span>
➷ Quartz 的具體實現
1. 程序直接啓動,創建任務調度的方式
<span style="font-size:18px;">package org.yscTest.action
public class TestMain{
private static Scheduler sched;
public static void run() throws Exception{
//創建LzstoneTimeTask的定時任務
JobDetail jobDetail = new JobDetail("MyJob",sched.DEFAULT_GROUP,MyTimeTask.class);
//目標 創建任務計劃,且定義執行時間爲 每天中午的12點執行該定時任務
CronTrigger trigger = new CronTrigger("MyTrigger","myTrigger","0 0 12 * * ?");
sched = new org.quartz.impl.StdSchedulerFactory().getScheduler();
//將當前定義的job和觸發器添加到任務調度器中進行管理
sched.scheduleJob(jobDetail,trigger);
//啓動任務調度器
sched.start();
}
//停止任務調度
public static void stop() throws Exception{
sched.shutdown();
}
}
//執行
public class Main{
.............
public void run(){
TestMain.run();
}
............
}</span>
2.web的監聽方式
<span style="font-size:18px;">package org.ysc.action public class TestMainListener implements ServletContextListener{ private Timer timer = null; //初始化監聽器,創建實例,執行任務 public void contextInitialized(ServletContextEvent event){ TestMain.run(); } //銷燬監聽器,停止執行任務 public void contextDestroyed(ServletContextEvent event){ TestMain.stop(); } }</span>
web.xml的配置:
<span style="font-size:18px;"><listener> <listener-class> org.ysc.action.TestMainListener </listener-class> </listener></span>
3.Timer 和Quartz的對比:
Timer的定時器,原理簡單,實現方便,上手容易;但是我們無法使用確切的時間(比如某天某點五十),並且我們要使用TImer必須繼承指定的類,所以依賴性較強;
Quartz定時器,方便,在日期的設定上更加靈活方便,可以實現比較複雜的定時任務,但是我們需要實現指定的接口,必須引入指定的jar包;
兩者的關係:
Quartz中有兩種觸發器,SimpleTrigger和CronTrigger,小編感覺:但從實現的方式和實現的效果來看,Timer和Quartz中的SimpleTrigger中是類似的,只是設定時長和間隔次數;
綜上所述,兩者各有各的優點,項目中的使用可以結合具體情況和定時的特點來選擇這兩種定時器;
➷ 擴展--spring的“”定時任務“
當提起spring時,我們第一反應都是它的IOC容器和aop日誌,但是很少想起spring對定時任務的支持;下面小編就將spring中對Timer和Quartz的支持一一道來:
1.對Timer的支持
♚ 創建定時任務類:
<span style="font-size:18px;">package org.test.action import java.util.TimeTask public class MyTimeTask extends TimeTask{ public void run(){ //執行的定時器任務 } }</span>
♚ 配置applicationContext.xml文件:
<span style="font-size:18px;"><!--註冊定時執行任務實體--> <bean id="lzstoneTimeTask" class="org.test.action.MyTimeTask3"/> <!--註冊定時器信息--> <bean id="taskInfo" class="org.springframework.scheduling.timer.ScheduledTimerTask"> <!--第一次執行任務前需要等待的時間,這裏設置爲3秒--> <property name="delay"> <value>3000</value> </property> <!--設置任務的執行週期 這裏設置爲4秒--> <property name="period"> <value>4000</value> </property> <!--設置具體執行的任務 這裏設置爲MyTimeTask3--> <property name="timerTask"> <ref local="MyTimeTask3"/> </property> </bean> <!--配置定時器任務的調度器--> <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean"> <!--註冊定時器列表--> <property name="scheduledTimerTasks"> <list> <ref local="taskInfo"/> ........ </list> </property> </bean></span>
♚ web項目中的啓動設置
<span style="font-size:18px;"><context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener></span>
2. 對Quartz的支持
♚ 創建定時任務類:
<span style="font-size:18px;">package org.test.action
public class MyQuartzTask{
public void execute(){
//執行的定時器任務
}
}</span>
♚ 在applicationContext.xml中進行配置:
<span style="font-size:18px;"><!--註冊定時執行任務實體-->
<bean id="MyQuartzTask" class="org.test.action.MyQuartzTask"/>
<!--註冊定時器信息-->
<bean id="taskInfo" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!--指定要執行的定時任務類 這裏是LzstoneQuartzTask-->
<property name="targetObject">
<ref local="MyQuartzTask"/>
</property>
<!--指定定時器任務類要執行的方法名稱 這裏是execute-->
<property name="targetMethod">
<value>execute</value>
</property>
</bean>
<!--配置定時器任務的調度器-->
<bean id="quartzTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<!--聲明要運行的實體-->
<property name="jobDetail">
<ref local="taskInfo"/>
</property>
<!--設置運行時間-->
<property name="cronExpression">
<value>0 0 12 * * ?</value>
</property>
</bean>
<!--註冊監聽器-->
<bean id="registerQuartz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!--註冊定時器實體 集合-->
<property name="triggers">
<list>
<ref local="quartzTrigger"/>
</list>
</property>
</bean></span>
如果我們需要使用Quartz框架來對既有程序中某個方法進行定期執行,可以使用以下的配置(以定時執行loadHomePageData方法爲例):
首先,我們引入quartz的包和指定的版本;
然後在ApplicationContext.xml中進行如下配置:
第一步:啓動觸發器的配置開始-->設定每一個觸發器對應的觸發器
第二步:調度的配置開始,設定每一個觸發器執行的頻率(由於使用的CronTrigger所以這裏我們使用的是克隆表達式)
第三步:給三個不同的任務指定要執行的方法
這樣,一旦quartz啓動,loadHomePageData的方法會以一個小時爲間隔重複執行;PS:第二步和第三步省略了另外兩個的配置;
以上就是小編對項目中定時任務應用的理解和總結,純屬個人理解,如有問題或者好的建議,請留言給小編哦!!