摘要:第一次在指定時(shí)間點(diǎn)執(zhí)行任務(wù),之后每隔時(shí)間調(diào)用任務(wù)一次。定時(shí)器已啟動(dòng)每隔小時(shí)已經(jīng)添加任務(wù)調(diào)度表這個(gè)方法在應(yīng)用服務(wù)被移除,沒有能力再接受請求的時(shí)候被調(diào)用。
1、普通thread實(shí)現(xiàn)
這是最常見的,創(chuàng)建一個(gè)thread,然后讓它在while循環(huán)里一直運(yùn)行著,通過sleep方法來達(dá)到定時(shí)任務(wù)的效果。這樣可以快速簡單的實(shí)現(xiàn),代碼如下:
public class Task1 { public static void main(String[] args) { // run in a second final long timeInterval = 1000; Runnable runnable = new Runnable() { public void run() { while (true) { // ------- code for task to run System.out.println("Hello !!"); // ------- ends here try { Thread.sleep(timeInterval); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread thread = new Thread(runnable); thread.start(); } }
2、用Timer和TimerTask
介紹
java.util.Timer定時(shí)器,實(shí)際上是個(gè)線程,定時(shí)調(diào)度所擁有的TimerTasks。
一個(gè)java.util.TimerTask實(shí)際上就是一個(gè)擁有run方法的類,需要定時(shí)執(zhí)行的代碼放到run方法體內(nèi),TimerTask一般是以匿名類的方式創(chuàng)建。
上面的實(shí)現(xiàn)是非常快速簡便的,但它也缺少一些功能。
用Timer和TimerTask的話與上述方法相比有如下好處:
當(dāng)啟動(dòng)和去取消任務(wù)時(shí)可以控制
第一次執(zhí)行任務(wù)時(shí)可以指定你想要的delay時(shí)間
在實(shí)現(xiàn)時(shí),Timer類可以調(diào)度任務(wù),TimerTask則是通過在run()方法里實(shí)現(xiàn)具體任務(wù)。
Timer實(shí)例可以調(diào)度多任務(wù),它是線程安全的。
當(dāng)Timer的構(gòu)造器被調(diào)用時(shí),它創(chuàng)建了一個(gè)線程,這個(gè)線程可以用來調(diào)度任務(wù)。
下面是代碼:
Timer 測試類代碼:
//import java.util.Date; import java.util.Timer; //import com.baibutao.apps.linkshop.uxiang.server.util.DateUtil; public class TestTimerTask { public static void main(String[] args){ TaskA taskA = new TaskA(); Timer timer = new Timer(); timer.schedule(taskA, 5 * 1000, 5 * 1000); //Date date = DateUtil.parse("2014-12-04 16:50:00"); //timer.schedule(taskA, date , 5 * 1000); //timer.scheduleAtFixedRate(taskA, date, 5 * 1000); } }
任務(wù)類代碼:
import java.util.Date; import java.util.TimerTask; import wint.lang.utils.DateUtil; // 定義一個(gè)任務(wù)類 public class TaskA extends TimerTask{ @Override public void run() { System.out.println(DateUtil.formatFullDate(new Date())); } }
關(guān)于Timer類的調(diào)用方法:
void java.util.Timer.schedule(TimerTask task, long delay):多長時(shí)間(毫秒)后執(zhí)行任務(wù)
void java.util.Timer.schedule(TimerTask task, Date time):設(shè)定某個(gè)時(shí)間執(zhí)行任務(wù)
void java.util.Timer.schedule(TimerTask task, long delay, long period):delay時(shí)間后開始執(zhí)行任務(wù),并每隔period時(shí)間調(diào)用任務(wù)一次。
void java.util.Timer.schedule(TimerTask task, Date firstTime, long period):第一次在指定firstTime時(shí)間點(diǎn)執(zhí)行任務(wù),之后每隔period時(shí)間調(diào)用任務(wù)一次。
void java.util.Timer.scheduleAtFixedRate(TimerTask task, long delay, long period):delay時(shí)間后開始執(zhí)行任務(wù),并每隔period時(shí)間調(diào)用任務(wù)一次。
void java.util.Timer.scheduleAtFixedRate(TimerTask task, long delay, long period):第一次在指定firstTime時(shí)間點(diǎn)執(zhí)行任務(wù),之后每隔period時(shí)間調(diào)用任務(wù)一次。
void java.util.Timer.cancel():終止該Timer
boolean java.util.TimerTask.cancel():終止該TimerTask
可以為每個(gè)Timer指定多個(gè)TimerTask
雖然可通過void java.util.Timer.schedule(TimerTask task, Date firstTime, long period)方法完成“例如:每天上午10點(diǎn)執(zhí)行一次”的業(yè)務(wù),但該實(shí)現(xiàn)是基于進(jìn)行一天(1000 * 60 * 60 * 24毫秒)進(jìn)行延遲的機(jī)制實(shí)現(xiàn)的,并不是指定某個(gè)具體時(shí)間進(jìn)行執(zhí)行的。
對于該種需求,可通過Quartz來進(jìn)行實(shí)現(xiàn)
方法名稱schedule()和scheduleAtFixedRate()兩者的區(qū)別
當(dāng)需要根據(jù)period區(qū)間時(shí)間循環(huán)多次調(diào)用任務(wù)的時(shí)候,會(huì)存在兩種不同的策略,兩種方法提供了不同的策略。
調(diào)用方法(1)、(2)只是單次執(zhí)行,不存在多次調(diào)用任務(wù)的情況,所以沒有提供scheduleAtFixedRate方法的調(diào)用方式。
schedule()方法更注重保持間隔時(shí)間的穩(wěn)定:保障每隔period時(shí)間可調(diào)用一次
scheduleAtFixedRate()方法更注重保持執(zhí)行頻率的穩(wěn)定:保障多次調(diào)用的頻率趨近于period時(shí)間,如果某一次調(diào)用時(shí)間大于period,下一次就會(huì)盡量小于period,以保障頻率接近于period
進(jìn)一步的說明參見eg366的博客,星星的技術(shù)專欄
3、ScheduledExecutorService
ScheduledExecutorService是從Java SE 5的java.util.concurrent里,做為并發(fā)工具類被引進(jìn)的,這是最理想的定時(shí)任務(wù)實(shí)現(xiàn)方式。
相比于上兩個(gè)方法,它有以下好處:
相比于Timer的單線程,它是通過線程池的方式來執(zhí)行任務(wù)的
可以很靈活的去設(shè)定第一次執(zhí)行任務(wù)delay時(shí)間
提供了良好的約定,以便設(shè)定執(zhí)行的時(shí)間間隔
下面是實(shí)現(xiàn)代碼,我們通過ScheduledExecutorService#scheduleAtFixedRate展示這個(gè)例子,通過代碼里參數(shù)的控制,首次執(zhí)行加了delay時(shí)間。
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class Task3 { public static void main(String[] args) { Runnable runnable = new Runnable() { public void run() { // task to run goes here System.out.println("Hello !!"); } }; ScheduledExecutorService service = Executors .newSingleThreadScheduledExecutor(); service.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.SECONDS); } }
關(guān)于ScheduledExecutorService 和 Timer的優(yōu)劣,Timer沒有很好的錯(cuò)誤處理機(jī)制,請參考苦行僧的博客
關(guān)于ScheduledExecutorService 的具體用法,請參照濤濤的博客
4、web容器中利用ServletContextListener實(shí)現(xiàn)定時(shí)任務(wù)
一個(gè)實(shí)現(xiàn)ServletContextListener接口的類: StatisticsContextListener.java:
package com.ed.cnc.servletListener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import com.ed.cnc.city.StatisticsTask; /** * 統(tǒng)計(jì)ContextListener * @author westd * */ /** * @author westd * */ public class StatisticsContextListener implements ServletContextListener { private java.util.Timer timer = null; /** * 這個(gè)方法在Web應(yīng)用服務(wù)做好接受請求的時(shí)候被調(diào)用。 * * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) */ public void contextInitialized(ServletContextEvent event) { timer = new java.util.Timer(true); event.getServletContext().log("定時(shí)器已啟動(dòng)"); timer.schedule(new StatisticsTask(event.getServletContext()), 0, 60*60*1000);//每隔1小時(shí) event.getServletContext().log("已經(jīng)添加任務(wù)調(diào)度表"); } /** * 這個(gè)方法在Web應(yīng)用服務(wù)被移除,沒有能力再接受請求的時(shí)候被調(diào)用。 * * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) */ public void contextDestroyed(ServletContextEvent event) { timer.cancel(); event.getServletContext().log("定時(shí)器銷毀"); } }
一個(gè)繼承于TimerTask的一個(gè)類:StatisticsTask.java
package com.ed.cnc.city; import java.util.Calendar; import java.util.TimerTask; import javax.servlet.ServletContext; /** * 統(tǒng)計(jì)任務(wù) * @author westd * */ public class StatisticsTask extends TimerTask { private static final int STATISTICS_SCHEDULE_HOUR = 0; private static boolean isRunning = false; private ServletContext context = null; public StatisticsTask(ServletContext context) { this.context = context; } @Override public void run() { Calendar cal = Calendar.getInstance(); //System.out.println(isRunning); if (!isRunning) { if (STATISTICS_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) //查看是否為凌晨 { isRunning = true; context.log("開始執(zhí)行指定任務(wù)"); //TODO 添加自定義的詳細(xì)任務(wù) executeTask(); //指定任務(wù)執(zhí)行結(jié)束 isRunning = false; context.log("指定任務(wù)執(zhí)行結(jié)束"); } } else { context.log("上一次任務(wù)執(zhí)行還未結(jié)束"); } } /** * 執(zhí)行任務(wù) */ public void executeTask() { System.out.println("任務(wù)1"); System.out.println("任務(wù)2"); }
}
web.xml中添加如下代碼:
com.ed.cnc.servletListener.StatisticsContextListener
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/64207.html
摘要:定時(shí)任務(wù)間隔時(shí)間方式執(zhí)行一次定時(shí)任務(wù)線程休眠規(guī)定時(shí)間類類允許調(diào)度一個(gè)任務(wù)。引入依賴配置測試執(zhí)行一次定時(shí)任務(wù)使用注解是為定時(shí)任務(wù)而生的一個(gè)注解,查看注解的源碼表達(dá)式接收一個(gè)。 本文旨在用通俗的語言講述枯燥的知識(shí) 定時(shí)任務(wù)作為一種系統(tǒng)調(diào)度工具,在一些需要有定時(shí)作業(yè)的系統(tǒng)中應(yīng)用廣泛,如每逢某個(gè)時(shí)間點(diǎn)統(tǒng)計(jì)數(shù)據(jù)、在將來某個(gè)時(shí)刻執(zhí)行某些動(dòng)作...定時(shí)任務(wù)在主流開發(fā)語言均提供相應(yīng)的API供開發(fā)者調(diào)用...
本文來自網(wǎng)絡(luò)一些博客的整理(包括gong1208的博客 dary1715的博客) 1、簡介 這個(gè)系列介紹Spring框架實(shí)現(xiàn)定時(shí)任務(wù)的兩種方式以及一些高級的用法,包括: 1、使用Quartz,這是一個(gè)功能比較強(qiáng)大的的調(diào)度器,可以讓你的程序在指定時(shí)間執(zhí)行,也可以按照某一個(gè)頻度執(zhí)行,配置起來稍顯復(fù)雜,稍后會(huì)詳細(xì)介紹。 2、Spring3.0以后自帶的task,可以將它看成一個(gè)輕量級的Quartz,而且...
摘要:有三種狀態(tài)運(yùn)行關(guān)閉終止。類類,提供了一系列工廠方法用于創(chuàng)建線程池,返回的線程池都實(shí)現(xiàn)了接口。線程池的大小一旦達(dá)到最大值就會(huì)保持不變,在提交新任務(wù),任務(wù)將會(huì)進(jìn)入等待隊(duì)列中等待。此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。 這是java高并發(fā)系列第19篇文章。 本文主要內(nèi)容 介紹Executor框架相關(guān)內(nèi)容 介紹Executor 介紹ExecutorService 介紹線程池ThreadP...
摘要:在之前,它是一個(gè)備受爭議的關(guān)鍵字,因?yàn)樵诔绦蛑惺褂盟占骼斫夂驮矸治龊喎Q,是后提供的面向大內(nèi)存區(qū)數(shù)到數(shù)多核系統(tǒng)的收集器,能夠?qū)崿F(xiàn)軟停頓目標(biāo)收集并且具有高吞吐量具有更可預(yù)測的停頓時(shí)間。 35 個(gè) Java 代碼性能優(yōu)化總結(jié) 優(yōu)化代碼可以減小代碼的體積,提高代碼運(yùn)行的效率。 從 JVM 內(nèi)存模型談線程安全 小白哥帶你打通任督二脈 Java使用讀寫鎖替代同步鎖 應(yīng)用情景 前一陣有個(gè)做...
摘要:也是自帶的一個(gè)基于線程池設(shè)計(jì)的定時(shí)任務(wù)類。其每個(gè)調(diào)度任務(wù)都會(huì)分配到線程池中的一個(gè)線程執(zhí)行,所以其任務(wù)是并發(fā)執(zhí)行的,互不影響。 原創(chuàng)不易,如需轉(zhuǎn)載,請注明出處https://www.cnblogs.com/baixianlong/p/10659045.html,否則將追究法律責(zé)任!!! 一、在JAVA開發(fā)領(lǐng)域,目前可以通過以下幾種方式進(jìn)行定時(shí)任務(wù) 1、單機(jī)部署模式 Timer:jdk中...
閱讀 3650·2021-10-12 10:11
閱讀 1013·2021-09-22 15:42
閱讀 3465·2019-08-30 13:06
閱讀 907·2019-08-29 17:05
閱讀 1650·2019-08-29 12:21
閱讀 2378·2019-08-29 11:31
閱讀 1135·2019-08-23 18:37
閱讀 1257·2019-08-23 14:58