いくつかのタスクスケジューリングのJava実装方法と比較2-読書
10981 ワード
Quartz
Quartzはより複雑なスケジューリング要件を満たすことができます.まず、毎週火曜日の16:38のスケジューリングをQuartzで実現する方法を見てみましょう.
インベントリ1:
出力結果:
インベントリ1は、上述した複雑なタスクスケジューリングを非常に簡潔に実現する.Quartzが設計したコアクラスには、Scheduler、Job、Triggerが含まれています.ここで、Jobは実行するタスクの定義を担当し、Triggerはスケジューリングポリシーの設定を担当し、Schedulerは両方を組み立て、タスクの実行を開始するようにトリガーします.
Job
利用者はJobの継承クラスを作成し,executeメソッドを実現するだけである.JobDetailは,JobおよびJobの属性をカプセル化し,これをSchedulerにパラメータとして提供する.Schedulerがタスクを実行するたびに、まずJobのインスタンスが作成され、executeメソッドの実行が呼び出されます.QuartzはJobに対してパラメータ付き構造関数を設計していないので,Jobの属性を追加のJobDataMapで格納する必要がある.JobDataMapは、任意の数のKey、Valueペアを格納できます.たとえば、次のようになります.
JobDataMapのデータは次のように取得できます.
出力結果:
Trigger
Triggerの役割はスケジューリングポリシーを設定することです.Quartzは、SimpleTriggerとCronTriggerが最も一般的なタイプのTriggerを設計しています.
SimpleTriggerは、ある特定の時間に1回実行するか、ある特定の時間間隔で複数回実行するのに適しています.上記の機能により、SimpleTriggerのパラメータには、start-time、end-time、repeat count、およびrepeat intervalが含まれる.
Repeat countの値はゼロ以上の整数、または定数SimpleTriggerである.REPEAT_INDEFINITELY.
Repeat intervalは、ゼロ以上の長さの整数を取ります.Repeat interval値がゼロであり、Repeat count値がゼロより大きい場合、タスクの同時実行がトリガーされます.
Start-timeとdnd-timeの値はjavaである.util.Date.end-timeとrepeat countを同時に指定する場合、end-timeが優先されます.一般に、end-timeを指定し、repeat countをREPEAT_に設定することができるINDEFINITELY.
以下はSimpleTriggerの構築方法です.
例を次に示します.
今すぐ実行し、一度だけ実行するSimpleTriggerを作成します.
30分後に実行を開始し、1分おきに繰り返し実行するSimpleTriggerを作成します.
2011年6月1日8時30分に実行を開始し、1時間ごとに実行し、合計100回実行し、1日後に終了するSimpleTriggerを作成します.
上記の最後の例では、end-timeとrepeat countを同時に設定すると、end-timeを優先して合計24回実行できる.
CronTriggerは、特定の時間間隔でスケジュールされたSimpleTriggerよりも、カレンダーベースのスケジュールに主に適用されるため、広く使用されています.たとえば、毎週火曜日の16:38:10実行、毎月1日実行、さらに複雑なスケジュールなどです.
CronTriggerもstart-timeとend-timeを指定する必要があります.その核心はCron式で、7つのフィールドから構成されています.
例を次に示します.
3時間ごとに実行されるCronTriggerを作成し、1時間ごとの整数点から実行します.
10分ごとに実行されるCronTriggerを作成し、3分ごとに実行を開始します.
毎週月曜日、火曜日、水曜日、土曜日の夜20:00から23:00まで、30分ごとにCronTriggerを実行します.
毎月最後の木曜日、昼11:30-14:30、1時間に1回のtriggerを作成します.
上記の例の各記号の意味を説明します.
まず、すべてのフィールドに独自の値があります.たとえば、SecondsとMinutesは0から59、Hoursは0から23、Day-of-Monthは0-31、Monthは0-11、またはJAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV、DEC、Days-of-Weekは1-7またはSUN、MON、TUE、WED、THU、FRI、SATです.各フィールドは、単一の値、複数の値、またはDay-of-Weekのような範囲で、「MON、TUE、SAT」、「MON-FRI」または「TUE-THU、SUN」の値をとることができる.
ワイルドカード*は、フィールドが任意の可能な値を受け入れることができることを示します.たとえば、Monthフィールド付与*は毎月、Day-of-Weekフィールド付与*は1週間の毎日を表します.
開始時刻と間隔期間を示す.たとえば、Minutesフィールドの割り当て2/10は、2分目から1時間に20分ごとに実行されることを示します.
? Day-of-MonthとDay-of-Weekにのみ適用されます.?フィールドに特定の値が指定されていないことを示します.この2つのフィールドのいずれかに値を指定する必要があり、他のフィールドに値を指定しない場合に適用されます.一般的に、この2つのフィールドは1つの値を割り当てるだけです.
Lは、Day-of-MonthおよびDay-of-Weekにのみ適用されます.LはDay-of-Monthに使用され、この月の最後の日を表します.Lは単独でDay-of-Weekに土曜日を表し、そうでなければ1ヶ月の最後の曜日を表し、例えば5 LまたはTHULはその月の最後の木曜日を表す.
WはDay-of-Monthにのみ適用され、指定した日付に最も近い営業日を表します.たとえば、Day-of-Monthは10 Wの値を割り当て、その月が10日に最も近い営業日を表します.
#Day-of-Weekにのみ適用され、その月のXXX番目の曜日を示します.例えば、Day-of-Weekは5#2またはTHU#2に割り当てられ、その月の第2木曜日を表す.
CronTriggerの使用方法は次のとおりです.
JobとTriggerの松結合設計はQuartzの大きな特徴であり,その利点は同じJobが複数の異なるTriggerをバインドでき,同じTriggerでも複数のJobをスケジューリングでき,柔軟性が強いことである.
Listener
上記の基本的なスケジューリング機能に加えて、Quartzはlistenerの機能も提供しています.主に3種類のlistener:JobListener,TriggerListenerおよびSchedulerListenerを含む.システムに障害が発生し、関係者が通知される必要がある場合、Listenerはその役割を果たすことができます.最も一般的なケースは、タスクが実行されると、システムに障害が発生し、Listenerがエラーを傍受し、すぐに管理者にメールを送信することです.次に、JobListenerの例を示します.
リスト2.JobListenerの実装
リスト2から分かるように,利用者はJobListenerの継承クラスを1つ作成するだけで,トリガが必要なメソッドを再ロードすればよい.もちろん、listenerのインプリメンテーションクラスをSchedulerとJobDetailに登録する必要があります.
ユーザーは、listenerをグローバルlistenerに登録することもできます.これにより、schedulerに登録されているすべてのタスクをリスニングできます.
listenerの機能をテストするためにjobのexecuteメソッドで異常を強制的に放出することができる.リスト7ではlistenerが異常を受信し、jobが存在するschedulerを停止し、後続のjobの実行を阻止する.scheduler、jobDetailなどの情報はlistenerのパラメータcontextから取得できます.
インベントリ2の出力結果は:
TriggerListener、SchedulerListenerはJobListenerと似たような機能を持っているが、JobListenerがトリガしたイベントのように、それぞれトリガしたイベントが異なる.
Job to be executed,Job has completed execution等
TriggerListenerによってトリガーされるイベントは次のとおりです.
Trigger firings,trigger mis-firings,trigger completionsなど
SchedulerListenerによってトリガーされたイベントは次のとおりです.
add a job/trigger,remove a job/trigger,shutdown a schedulerなど
読者は自分のニーズに応じて対応するイベントを再ロードすることができます.
Quartzはより複雑なスケジューリング要件を満たすことができます.まず、毎週火曜日の16:38のスケジューリングをQuartzで実現する方法を見てみましょう.
インベントリ1:
package com.ibm.scheduler;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.helpers.TriggerUtils;
public class QuartzTest implements Job {
@Override
//
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("Generating report - "
+ arg0.getJobDetail().getFullName() + ", type ="
+ arg0.getJobDetail().getJobDataMap().get("type"));
System.out.println(new Date().toString());
}
public static void main(String[] args) {
try {
// Scheduler
SchedulerFactory schedFact =
new org.quartz.impl.StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();
sched.start();
// JobDetail, name,groupname, Job ,
// Job
JobDetail jobDetail = new JobDetail("myJob", "myJobGroup",
QuartzTest.class);
jobDetail.getJobDataMap().put("type", "FULL");
// Trigger,
Trigger trigger = TriggerUtils.makeWeeklyTrigger(3, 16, 38);
trigger.setGroup("myTriggerGroup");
//
trigger.setStartTime(TriggerUtils.getEvenSecondDate(new Date()));
// trigger name
trigger.setName("myTrigger");
// scheduler JobDetail Trigger ,
sched.scheduleJob(jobDetail, trigger);
} catch (Exception e) {
e.printStackTrace();
}
}
}
出力結果:
/**
:
Generating report - myJobGroup.myJob, type =FULL
Tue Feb 8 16:38:00 CST 2011
Generating report - myJobGroup.myJob, type =FUL
Tue Feb 15 16:38:00 CST 2011
*/
インベントリ1は、上述した複雑なタスクスケジューリングを非常に簡潔に実現する.Quartzが設計したコアクラスには、Scheduler、Job、Triggerが含まれています.ここで、Jobは実行するタスクの定義を担当し、Triggerはスケジューリングポリシーの設定を担当し、Schedulerは両方を組み立て、タスクの実行を開始するようにトリガーします.
Job
利用者はJobの継承クラスを作成し,executeメソッドを実現するだけである.JobDetailは,JobおよびJobの属性をカプセル化し,これをSchedulerにパラメータとして提供する.Schedulerがタスクを実行するたびに、まずJobのインスタンスが作成され、executeメソッドの実行が呼び出されます.QuartzはJobに対してパラメータ付き構造関数を設計していないので,Jobの属性を追加のJobDataMapで格納する必要がある.JobDataMapは、任意の数のKey、Valueペアを格納できます.たとえば、次のようになります.
jobDetail.getJobDataMap().put("myDescription", "my job description");
jobDetail.getJobDataMap().put("myValue", 1998);
ArrayList<String> list = new ArrayList<String>();
list.add("item1");
jobDetail.getJobDataMap().put("myArray", list);
JobDataMapのデータは次のように取得できます.
public class JobDataMapTest implements Job {
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
// context instName,groupName dataMap
String instName = context.getJobDetail().getName();
String groupName = context.getJobDetail().getGroup();
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
// dataMap myDescription,myValue myArray
String myDescription = dataMap.getString("myDescription");
int myValue = dataMap.getInt("myValue");
ArrayList<String> myArray = (ArrayListlt;Strin>) dataMap.get("myArray");
System.out.println("
Instance =" + instName + ", group = " + groupName
+ ", description = " + myDescription + ", value =" + myValue
+ ", array item0 = " + myArray.get(0));
}
}
出力結果:
/**
:
Instance = myJob, group = myJobGroup,
description = my job description,
value =1998, array item0 = item1
*/
Trigger
Triggerの役割はスケジューリングポリシーを設定することです.Quartzは、SimpleTriggerとCronTriggerが最も一般的なタイプのTriggerを設計しています.
SimpleTriggerは、ある特定の時間に1回実行するか、ある特定の時間間隔で複数回実行するのに適しています.上記の機能により、SimpleTriggerのパラメータには、start-time、end-time、repeat count、およびrepeat intervalが含まれる.
Repeat countの値はゼロ以上の整数、または定数SimpleTriggerである.REPEAT_INDEFINITELY.
Repeat intervalは、ゼロ以上の長さの整数を取ります.Repeat interval値がゼロであり、Repeat count値がゼロより大きい場合、タスクの同時実行がトリガーされます.
Start-timeとdnd-timeの値はjavaである.util.Date.end-timeとrepeat countを同時に指定する場合、end-timeが優先されます.一般に、end-timeを指定し、repeat countをREPEAT_に設定することができるINDEFINITELY.
以下はSimpleTriggerの構築方法です.
public SimpleTrigger(String name,
String group,
Date startTime,
Date endTime,
int repeatCount,
long repeatInterval)
例を次に示します.
今すぐ実行し、一度だけ実行するSimpleTriggerを作成します.
SimpleTrigger trigger=
new SimpleTrigger("myTrigger", "myGroup", new Date(), null, 0, 0L);
30分後に実行を開始し、1分おきに繰り返し実行するSimpleTriggerを作成します.
SimpleTrigger trigger=
new SimpleTrigger("myTrigger", "myGroup",
new Date(System.currentTimeMillis()+30*1000), null, 0, 60*1000);
2011年6月1日8時30分に実行を開始し、1時間ごとに実行し、合計100回実行し、1日後に終了するSimpleTriggerを作成します.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2011);
calendar.set(Calendar.MONTH, Calendar.JUNE);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR, 8);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date startTime = calendar.getTime();
Date endTime = new Date (calendar.getTimeInMillis() +24*60*60*1000);
SimpleTrigger trigger=new SimpleTrigger("myTrigger",
"myGroup", startTime, endTime, 100, 60*60*1000);
上記の最後の例では、end-timeとrepeat countを同時に設定すると、end-timeを優先して合計24回実行できる.
CronTriggerは、特定の時間間隔でスケジュールされたSimpleTriggerよりも、カレンダーベースのスケジュールに主に適用されるため、広く使用されています.たとえば、毎週火曜日の16:38:10実行、毎月1日実行、さらに複雑なスケジュールなどです.
CronTriggerもstart-timeとend-timeを指定する必要があります.その核心はCron式で、7つのフィールドから構成されています.
Seconds
Minutes
Hours
Day-of-Month
Month
Day-of-Week
Year (Optional field)
例を次に示します.
3時間ごとに実行されるCronTriggerを作成し、1時間ごとの整数点から実行します.
0 0 0/3 * * ?
10分ごとに実行されるCronTriggerを作成し、3分ごとに実行を開始します.
0 3/10 * * * ?
毎週月曜日、火曜日、水曜日、土曜日の夜20:00から23:00まで、30分ごとにCronTriggerを実行します.
0 0/30 20-23 ? * MON-WED,SAT
毎月最後の木曜日、昼11:30-14:30、1時間に1回のtriggerを作成します.
0 30 11-14/1 ? * 5L
上記の例の各記号の意味を説明します.
まず、すべてのフィールドに独自の値があります.たとえば、SecondsとMinutesは0から59、Hoursは0から23、Day-of-Monthは0-31、Monthは0-11、またはJAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV、DEC、Days-of-Weekは1-7またはSUN、MON、TUE、WED、THU、FRI、SATです.各フィールドは、単一の値、複数の値、またはDay-of-Weekのような範囲で、「MON、TUE、SAT」、「MON-FRI」または「TUE-THU、SUN」の値をとることができる.
ワイルドカード*は、フィールドが任意の可能な値を受け入れることができることを示します.たとえば、Monthフィールド付与*は毎月、Day-of-Weekフィールド付与*は1週間の毎日を表します.
開始時刻と間隔期間を示す.たとえば、Minutesフィールドの割り当て2/10は、2分目から1時間に20分ごとに実行されることを示します.
? Day-of-MonthとDay-of-Weekにのみ適用されます.?フィールドに特定の値が指定されていないことを示します.この2つのフィールドのいずれかに値を指定する必要があり、他のフィールドに値を指定しない場合に適用されます.一般的に、この2つのフィールドは1つの値を割り当てるだけです.
Lは、Day-of-MonthおよびDay-of-Weekにのみ適用されます.LはDay-of-Monthに使用され、この月の最後の日を表します.Lは単独でDay-of-Weekに土曜日を表し、そうでなければ1ヶ月の最後の曜日を表し、例えば5 LまたはTHULはその月の最後の木曜日を表す.
WはDay-of-Monthにのみ適用され、指定した日付に最も近い営業日を表します.たとえば、Day-of-Monthは10 Wの値を割り当て、その月が10日に最も近い営業日を表します.
#Day-of-Weekにのみ適用され、その月のXXX番目の曜日を示します.例えば、Day-of-Weekは5#2またはTHU#2に割り当てられ、その月の第2木曜日を表す.
CronTriggerの使用方法は次のとおりです.
CronTrigger cronTrigger = new CronTrigger("myTrigger", "myGroup");
try {
cronTrigger.setCronExpression("0 0/30 20-13 ? * MON-WED,SAT");
} catch (Exception e) {
e.printStackTrace();
}
JobとTriggerの松結合設計はQuartzの大きな特徴であり,その利点は同じJobが複数の異なるTriggerをバインドでき,同じTriggerでも複数のJobをスケジューリングでき,柔軟性が強いことである.
Listener
上記の基本的なスケジューリング機能に加えて、Quartzはlistenerの機能も提供しています.主に3種類のlistener:JobListener,TriggerListenerおよびSchedulerListenerを含む.システムに障害が発生し、関係者が通知される必要がある場合、Listenerはその役割を果たすことができます.最も一般的なケースは、タスクが実行されると、システムに障害が発生し、Listenerがエラーを傍受し、すぐに管理者にメールを送信することです.次に、JobListenerの例を示します.
リスト2.JobListenerの実装
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
import org.quartz.SchedulerException;
public class MyListener implements JobListener{
@Override
public String getName() {
return "My Listener";
}
@Override
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException) {
if(jobException != null){
try {
// Scheduler
context.getScheduler().shutdown();
System.out.println("
Error occurs when executing jobs, shut down the scheduler ");
// …
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
}
リスト2から分かるように,利用者はJobListenerの継承クラスを1つ作成するだけで,トリガが必要なメソッドを再ロードすればよい.もちろん、listenerのインプリメンテーションクラスをSchedulerとJobDetailに登録する必要があります.
sched.addJobListener(new MyListener());
jobDetail.addJobListener("My Listener"); // listener
ユーザーは、listenerをグローバルlistenerに登録することもできます.これにより、schedulerに登録されているすべてのタスクをリスニングできます.
sched.addGlobalJobListener(new MyListener());
listenerの機能をテストするためにjobのexecuteメソッドで異常を強制的に放出することができる.リスト7ではlistenerが異常を受信し、jobが存在するschedulerを停止し、後続のjobの実行を阻止する.scheduler、jobDetailなどの情報はlistenerのパラメータcontextから取得できます.
インベントリ2の出力結果は:
Generating report - myJob.myJob, type =FULL
Tue Feb 15 18:57:35 CST 2011
2011-2-15 18:57:35 org.quartz.core.JobRunShell run
: Job myJob.myJob threw a JobExecutionException:
org.quartz.JobExecutionException
at com.ibm.scheduler.QuartzListenerTest.execute(QuartzListenerTest.java:22)
at org.quartz.core.JobRunShell.run(JobRunShell.java:191)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:516)
2011-2-15 18:57:35 org.quartz.core.QuartzScheduler shutdown
: Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
Error occurs when executing jobs, shut down the scheduler
TriggerListener、SchedulerListenerはJobListenerと似たような機能を持っているが、JobListenerがトリガしたイベントのように、それぞれトリガしたイベントが異なる.
Job to be executed,Job has completed execution等
TriggerListenerによってトリガーされるイベントは次のとおりです.
Trigger firings,trigger mis-firings,trigger completionsなど
SchedulerListenerによってトリガーされたイベントは次のとおりです.
add a job/trigger,remove a job/trigger,shutdown a schedulerなど
読者は自分のニーズに応じて対応するイベントを再ロードすることができます.