如果引用或轉貼,麻煩註明出處與本網誌連結,否則視為侵權。

2005年8月17日

使用標準的Java Timer API執行Scheduled Job

FredWang (http://fredwang.blogspot.com)
2005/08/17

有些事情或技術沒有記下來, 時間一過就忘記了, 下次用到又要花許多時間回憶與研究, 因此用Blog做筆記作為備忘

第一節. 在Server端Stand-alone執行的Job

範例一 : 立即執行, 每三分鐘執行一次
/* class ReportGenerator */
package sche.*;
import java.util.Date;
import java.util.TimerTask;
public class ReportGenerator extends TimerTask {
public void run() {
Date now = new Date();
System.out.println("Generating report:"+now.getTime());
//TODO generate report
}
}

/* class MainApplication */
package sche.*;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class MainApplication {
public static void main(String[] args) {
Timer timer = new Timer();
Date now = new Date();
// 立即執行, 每三分鐘執行一次
timer.schedule(
new ReportGenerator(),
now,
1000 * 60 * 3
);
}

範例二 : 每週日午夜零時執行一次
/* class MainApplication */
package sche.*;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class MainApplication {
public static void main(String[] args) {
Timer timer = new Timer();
Calendar date = Calendar.getInstance();
date.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
date.set(Calendar.HOUR, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
// 每週日午夜零時執行一次
timer.schedule(
new ReportGenerator(),
date.getTime(),
1000 * 60 * 60 * 24 * 7
);
}
註 : ReportGenerator程式不變

第二節. 用JSP來控制Job的啟動與關閉

/* 立即執行, 每三分鐘執行一次 */
package sche.*;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerService {
Timer timer = new Timer();
public TimerService() { };
public void start() throws Exception {
Date now = new Date();
// 立即執行, 每三分鐘執行一次
timer.schedule(
new ReportGenerator(),
now,
1000 * 60 * 3
);
}
public void stop() throws Exception {
timer.cancel();
}
}
註 : ReportGenerator程式不變

JSP程式範例
1. scheControl.jsp : 根據application屬性, 顯示開始或停止的按鈕

<%@ page import="sche.*" %>
<form action="sche.jsp" method="post">
<%
TimerService service = (TimerService)application.getAttribute("timerService");
if(service == null) {
out.print("<input type=submit value='Start Service'>");
} else {
out.print("<input type=submit value='Stop Service'>");
}
%>
</form>


2. sche.jsp : 根據application屬性決定開始或停止

<%@ page contentType="text/html; charset=Big5" %>
<%@ page import="sche.*" %>
<%
TimerService service = (TimerService)application.getAttribute("timerService");
boolean isStart = true;
if(service == null) {
service = new TimerService();
application.setAttribute("timerService",service);
service.start();
System.out.println("Timer service is startup.");
} else {
service.stop();
isStart = false;
service = null;
application.removeAttribute("timerService");
System.out.println("Timer service is stop.");
}

%>
<html>
<body>
<%=(isStart?"start ok":"stop ok")%>
</body>
</html>


第三節 其他
其他進一步的做法有 :
1. 將TimerService改寫為服務多個Job的Service[2]
2. 利用Servlet Context Listerner來啟動與關閉Service (實作javax.servlet.ServletContextListener的contextInitialized() and contextDestoryed() [3]
3. 使用Quzrtz API建構功能更強大的Job-scheduling System, 例如: Persistence(持續性), 可以不因系統當機重開, 造成Jobs的消失, 且提供比Java Timer API更有彈性的定時驅動方式, 例如每週六及周日的中午12點才執行, 可以分別管理許多不同的Jobs與不同驅動方式(Triggers) [1]

參考 :
1. Dejan Bosanac, "OnJava.com : Java Scheduling in Java", 03/10/2004, http://www.onjava.com/lpt/a/4637
2. "一個簡單的timer service", http://66feifei.com/info_Print.asp?ArticleID=140
3. 徐榮勝, "如何在Web工程中實現任務計畫調度"

沒有留言:

張貼留言

歡迎提供意見, 謝謝 (註 : 留言經過版主審核通過才會發布)