Java实现定时调度的三种方法
1、Timer
Timer myTimer = new Timer(); ?
? ? ? ? myTimer.schedule(new Worker(), 1000);//1秒后執行 ?// ? ? ?2012-02-28 09:58:00執行 ?
? ? ? ? myTimer.schedule(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00")); ?
? ? ? ? myTimer.schedule(new Worker(), 5000,1000);//5秒后執行 每一秒執行一次 ?
// ? ? ?2012-02-28 09:58:00執行一次 以后每秒執行一次,如果設定的時間點在當前時間之前,任務會被馬上執行,然后開始按照設定的周期定時執行任務 ?
? ? ? ? myTimer.schedule(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"),1000); ?
? ? ? ? myTimer.scheduleAtFixedRate(new Worker(), 5000,1000);//5秒后執行 每一秒執行一次 如果該任務因為某些原因(例如垃圾收集)而延遲執行,那么接下來的任務會盡可能的快速執行,以趕上特定的時間點 ?
? ? ? ? myTimer.scheduleAtFixedRate(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"),1000);//和上個類似 ?
timer的缺點:
(1)Timer對調度的支持是基于絕對時間,而不是相對時間的,由此任務對系統時鐘的改變是敏感的;
(2)所有的TimerTask只有一個線程TimerThread來執行,因此同一時刻只有一個TimerTask在執行;
(3)Timer線程并不捕獲異常,所以任何一個TimerTask的執行異常都會導致Timer終止所有任務;這種情況下,Timer也不會再重新恢復線程的執行了;它錯誤的認為整個Timer都被取消了。此時,已經被安排但尚未執行的TimerTask永遠不會再執行了,新的任務也不能被調度了。
因此你應該考慮使用ScheduledThreadPoolExecutor作為代替品,ScheduledThreadExecutor只支持相對時間。
2、ScheduleExecutorService
ScheduleExecutorService接口中有四個重要的方法,其中scheduleAtFixedRate和scheduleWithFixedDelay在實現定時程序時比較方便。
(1)scheduleAtFixedRate
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, ?
? ? ? ? ? ? long initialDelay, ?
? ? ? ? ? ? long period, ?
? ? ? ? ? ? TimeUnit unit); ?
command:執行線程
initialDelay:初始化延時
period:兩次開始執行最小間隔時間
unit:計時單位
(2)scheduleWithFixedDelay
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, ?
? ? ? ? ? ? ? ? long initialDelay, ?? ? ? ? ? ? ? ? long delay, ?
? ? ? ? ? ? ? ? TimeUnit unit); ?
command:執行線程
initialDelay:初始化延時
period:前一次執行結束到下一次執行開始的間隔時間(間隔執行延遲時間)
unit:計時單位
(3)功能示例
1.按指定頻率周期執行某個任務。初始化延遲0ms開始執行,每隔100ms重新執行一次任務。
/**?
?* 以固定周期頻率執行任務?
?*/ ?
public static void executeFixedRate() { ?
? ? ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); ?
? ? executor.scheduleAtFixedRate( ?
? ? ? ? ? ? new EchoServer(), ?
? ? ? ? ? ? 0, ?
? ? ? ? ? ? 100, ?
? ? ? ? ? ? TimeUnit.MILLISECONDS); ?
} ?
間隔指的是連續兩次任務開始執行的間隔。
對于scheduleAtFixedRate方法,當執行任務的時間大于我們指定的間隔時間時,它并不會在指定間隔時開辟一個新的線程并發執行這個任務。而是等待該線程執行完畢。
初始化時延時0ms開始執行,本次執行結束后延遲100ms開始下次執行。
/**?
?* 以固定延遲時間進行執行?
?* 本次任務執行完成后,需要延遲設定的延遲時間,才會執行新的任務?
?*/ ?
public static void executeFixedDelay() { ?
? ? ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); ?
? ? executor.scheduleWithFixedDelay( ?
? ? ? ? ? ? new EchoServer(), ?
? ? ? ? ? ? 0, ?
? ? ? ? ? ? 100, ?
? ? ? ? ? ? TimeUnit.MILLISECONDS); ?
} ?
間隔指的是連續上次執行完成和下次開始執行之間的間隔。
3.周期定時執行某個任務。
/**?
?* 每天晚上8點執行一次?
?* 每天定時安排任務進行執行?
?*/ ?
public static void executeEightAtNightPerDay() { ?
? ? ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); ?
? ? long oneDay = 24 * 60 * 60 * 1000; ?
? ? long initDelay ?= getTimeMillis("20:00:00") - System.currentTimeMillis(); ?
? ? initDelay = initDelay > 0 ? initDelay : oneDay + initDelay; ?
??
? ? executor.scheduleAtFixedRate( ?
? ? ? ? ? ? new EchoServer(), ?
? ? ? ? ? ? initDelay, ?
? ? ? ? ? ? oneDay, ?
? ? ? ? ? ? TimeUnit.MILLISECONDS); ?
} ?
/**?
?* 獲取指定時間對應的毫秒數?
?* @param time "HH:mm:ss"?
?* @return?
?*/ ?
private static long getTimeMillis(String time) { ?
? ? try { ?
? ? ? ? DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); ?
? ? ? ? DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd"); ?
? ? ? ? Date curDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time); ?
? ? ? ? return curDate.getTime(); ?
? ? } catch (ParseException e) { ?
? ? ? ? e.printStackTrace(); ?
? ? } ?
? ? return 0; ?
} ?
3、Spring
除了我們自己實現定時任務之外,我們可以使用Spring幫我們完成這樣的事情。
Spring自動定時任務配置方法(我們要執行任務的類名為com.study.MyTimedTask)
<bean id="myTimedTask" class="com.study.MyTimedTask"/> ?
<bean id="doMyTimedTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> ?
? ? <property name="targetObject" ref="myTimedTask"/> ?
? ? <property name="targetMethod" value="execute"/> ?
? ? <property name="concurrent" value="false"/> ?
</bean> ?
<bean id="myTimedTaskTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> ?
? ? <property name="jobDetail" ref="doMyTimedTask"/> ?
? ? <property name="cronExpression" value="0 0 2 * ?"/> ?
</bean> ?
<bean id="doScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> ?
? ? <property name="triggers"> ?
? ? ? ? <list> ?
? ? ? ? ? ? <ref local="myTimedTaskTrigger"/> ?
? ? ? ? </list> ?
? ? </property> ?
</bean> ?
<bean id="doScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> ?
? ? <property name="triggers"> ?
? ? ? ? <list> ?
? ? ? ? ? ? <bean class="org.springframework.scheduling.quartz.CronTriggerBean"> ?
? ? ? ? ? ? ? ? <property name="jobDetail"/> ?
? ? ? ? ? ? ? ? ? ? <bean id="doMyTimedTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> ?
? ? ? ? ? ? ? ? ? ? ? ? <property name="targetObject"> ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? <bean class="com.study.MyTimedTask"/> ?
? ? ? ? ? ? ? ? ? ? ? ? </property> ?
? ? ? ? ? ? ? ? ? ? ? ? <property name="targetMethod" value="execute"/> ?
? ? ? ? ? ? ? ? ? ? ? ? <property name="concurrent" value="false"/> ?
? ? ? ? ? ? ? ? ? ? </bean> ?
? ? ? ? ? ? ? ? </property> ?
? ? ? ? ? ? ? ? <property name="cronExpression" value="0 0 2 * ?"/> ?
? ? ? ? ? ? </bean> ?
? ? ? ? </list> ?
? ? </property> ?
</bean> ?
總結
以上是生活随笔為你收集整理的Java实现定时调度的三种方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 校验银行卡号
- 下一篇: Java常用软件教程