Quartzベース


Quartzはjavaによって完全に作成されたオープンソースジョブスケジューリングフレームワークです.サイクルワークのニーズに対応
1.Quartzの起動
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();

sched.start();
JobDetail jobDetail = new JobDetail("myJob", null, DumbJob.class);

Trigger trigger = TriggerUtils.makeHourlyTrigger(); // fire every hour
trigger.setStartTime(TriggerUtils.getEvenHourDate(new Date())); // start on the next even hour
trigger.setName("myTrigger");

sched.scheduleJob(jobDetail, trigger);

schedulerがインスタンス化されると、起動(start)され、シャットダウン(shutdown)されるまで常駐モードになります.schedulerが閉じられると、インスタンス化しない限り、schedulerは再起動できません.
2. Jobs And Triggers
Jobインタフェースはスケジューリングタスクの親であり、実行する必要があるすべてのコードはJobの実装にあります.
package org.quartz;
public interface Job {

    public void execute(JobExecutionContext context)
      throws JobExecutionException;
}

ジョブトリガがトリガーされた場合(ある時点)、Execute(.)schedulerに呼び出されます.JobExecutionContextオブジェクトはこのメソッドに渡され、Jobインスタンスの「ランタイム」環境を提供します.このIJobインスタンスを実行するSchedulerハンドル、この実行をトリガーするハンドル、IJobのJobDetailオブジェクト、およびいくつかの他のエントリを指します.
JobDetailオブジェクトは、Quartzクライアントによって、Jobがschedulerに追加されたときに作成されます.これには、指定されたジョブクラスインスタンスのステータス情報を格納するために使用されるJobの様々な設定プロパティと、指定されたJobDataMapオブジェクトが含まれています.
Triggerオブジェクトはjobsの実行をトリガするために使用されます.タスクを進捗に組み込むには、Triggerをインスタンス化し、そのプロパティを「調整」して、進捗スケジュールを満たす必要があります.TriggersにもJobDataMapが関連付けられており、トリガによってトリガされたJobへのパラメータの伝達に非常に有利である.
QuartzはさまざまなタイプのTriggerをパッケージ化していますが、最も一般的なTriggeクラスはSimpleTriggerとCronTriggerです.SimpleTriggerは、1回または所定の時間に1回だけトリガーし、N回繰り返し、一定時間遅延するタスクを実行するたびにトリガーするために使用される.CronTriggerはカレンダーに従ってトリガーされ、例えば「毎週金曜日」、毎月10日昼か10:15分です. 
なぜジョブズとTriggersに分けたのですか?多くのタスクスケジュールマネージャはJobsとTriggersを区別していません.一部の製品では、「job」を単純に小さなタスクID付きの実行時間として定義しているだけです.他の製品はQuartzのjobとtriggerの連合に似ています.Quartzを開発する際には、スケジュールとスケジュールに沿った作業を分離することにしました.(我々の観点から)これは多くの利点がある.例えば、jobsはtriggerに依存することなくjob schedulerに作成され、格納され得る.また、多くのtriggersはjobを関連付けることができる.別の利点は、このような「松結合」である.スケジュール内のJobに関連するtriggerを期限切れにして再構成することで、再定義することなく、後でスケジュールに再組み入れることができます.これにより、接続されたjob識別子を再定義することなくtriggerを変更または置換することができる.
Quartz schedulerにJobsとTriggersを登録すると、それらを識別する名前が与えられます.JobsとTriggersも「グループ」に入れることができます.「グループ」は、後続のメンテナンス中にJobsとTriggersを分類管理するのに役立ちます.JobsとTriggersの名前はグループの中で唯一でなければならない.言い換えれば、JobsとTriggersの本当の名前はその名前+グループである.JobまたはTriggerのグループをnullとすると、これはデフォルトのSchedulerに入れることに等しい.DEFAULT_GROUPグループにあります.
3.JobsとJobDetailsについて
実装クラスが真の"Job"となる場合には、タスクが持つ様々な属性をQuartzに通知する必要があり、JobDetailクラスによってこの作業を完了することができる.
 
JobDetail jobDetail = new JobDetail("myJob",         // job name
                                      sched.DEFAULT_GROUP,   // job group (you can also specify 'null' to use the default group)
                                      DumbJob.class);        // the java class to execute

Trigger trigger = TriggerUtils.makeDailyTrigger(8, 30);
trigger.setStartTime(new Date());
trigger.setName("myTrigger");

sched.scheduleJob(jobDetail, trigger);

public class DumbJob implements Job {
    public DumbJob() {
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    {
      System.err.println("DumbJob is executing.");
    }
}

 
注意:我々はschedulerにJobDetailインスタンスを渡し、JobDetailはjobを関連付け、jobのclassを提供し、schedulerがjobを実行するたびにexecute(...)を実行する.これまでにインスタンスが作成されます.jobには無パラメトリック構造方法が必要である.
構成jobのインスタンスをどのように提供するかを聞きたいかもしれません.あるいはjob状態を実行中に保存する.答えはJobDataMapです.JobDetailの一部です
JobDataMap 
JobDataMapは、Jobの実行時に入手可能な一連の(シーケンス化された)オブジェクトを保存するために使用される.
JobDataMapはMapインタフェースの実装であり、プライマリ・タイプのデータを格納および読み出すための便利な方法もいくつか追加されています.
jobDetail.getJobDataMap().put("jobSays", "Hello World!");
jobDetail.getJobDataMap().put("myFloatValue", 3.141f);
jobDetail.getJobDataMap().put("myStateData", new ArrayList());
次のコードは、ジョブ実行中にジョブデータマップからデータを取得するコードを示しています.
 
public class DumbJob implements Job {
    public DumbJob() {
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    {
      String instName = context.getJobDetail().getName();
      String instGroup = context.getJobDetail().getGroup();

      JobDataMap dataMap = context.getJobDetail().getJobDataMap();

      String jobSays = dataMap.getString("jobSays");
      float myFloatValue = dataMap.getFloat("myFloatValue");
      ArrayList state = (ArrayList)dataMap.get("myStateData");
      state.add(new Date());

      System.err.println("Instance " + instName + " of DumbJob says: " + jobSays);
    }
}

 
TriggersにはJobDataMapsが関連付けられていてもよい.scheduler中のJobが複数の規則的または反復的にトリガされたTriggersによって使用される場合に非常に有用である.独立したトリガのたびに、Jobに異なる入力データを提供することができます.Job実行時のJobExecutionContextからJobDataMapを取得するのは慣用手段であり、JobDetailとTriggerから取得したJobDataMapを融合させ、同じ名前のキーがある場合は後者の値で前者の値を上書きする.
StatefulJob-ステータスタスクあり
ここで、Jobステータスデータに関するいくつかの追加の論題は、1つのJobインスタンスを「ステータスあり」または「ステータスなし」と定義することができる.ステータスレスタスクには、schedulerに追加されたときに格納されたJobDataMapのみが含まれます.これは、ジョブの実行中にジョブData Mapに対する変更が失われ、ジョブが次回実行されるときも表示されないことを意味します.ステータスのあるタスクは正反対で、タスクの実行のたびにJobDataMapを再格納すると推測されます.ステータスタスクの副作用の1つは、同時に実行できないことです.すなわち、タスクにステータスがある場合、トリガがこのタスクを実行するときにトリガをトリガしようとすると、そのトリガは、前の実行が完了するまでブロック(待機)される.タスクにステータスを持たせるには、ジョブインタフェースではなくStatefulJobインタフェースを実現する.
jobsの他のプロパティ
ここでは、JobDetailオブジェクトによってJobの他の属性を定義できることを簡単にまとめます. 
Durability(永続性)-Jobが永続的でない場合、トリガが関連付けられていないとschedulerから自動的に削除されます.
Volatility(無常性)-Jobが無常である場合、Quartz i schedulerを再起動すると保持できません.
RequestsRecovery(リカバリを要求)-ジョブがリカバリを要求する機能を備えている場合、実行時にschedulerの「ハードクローズ」に遭遇します.
(たとえば、実行中のプロシージャがクラッシュしたり、コンピュータがシャットダウンされたり)すると、schedulerが再起動すると、このタスクは再実行されます.
この場合、JobExecutionContext.isRecovering()プロパティはtrueになります. 
JobListeners(タスクListener)-1つのJobが0つ以上のJobListeners Listenerに関連付けられている場合、このJobが実行されるとListenerが通知されます.
4.Triggersの詳細について
Priority
複数のTriggersがある場合、Quartzはscheduledのtriggerを同時に処理するのに十分なリソースがない場合がある.どちらが先に実行するかを制御する必要がありますこの場合、N個のtriggerが同時にトリガーされない場合はTriggerのpriorityを設定します.ただし、この場合、限られたスレッドはいくつかしかありません.
使用するこの場合、レベルの高いtriggerを先に処理する.レベルを設定していない場合は、デフォルトは5です.次に例を示します.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, 5);

Trigger trig1 = new SimpleTrigger("T1", "MyGroup", cal.getTime());
Trigger trig2 = new SimpleTrigger("T2", "MyGroup", cal.getTime());
Trigger trig3 = new SimpleTrigger("T3", "MyGroup", cal.getTime());

JobDetail jobDetail = new JobDetail("MyJob", "MyGroup", NoOpJob.class);

// Trigger1 does not have its priority set, so it defaults to 5
sched.scheduleJob(jobDetail, trig1);

// Trigger2 has its priority set to 10
trig2.setJobName(jobDetail.getName());
trig2.setPriority(10);
sched.scheduleJob(trig2);

// Trigger2 has its priority set to 1
trig3.setJobName(jobDetail.getName());
trig2.setPriority(1);
sched.scheduleJob(trig3);

// Five minutes from now, when the scheduler invokes these three triggers
// they will be allocated worker threads in decreasing order of their
// priority: Trigger2(10), Trigger1(5), Trigger3(1)

 
Misfire Instructions-未トリガ命令
Triggerのもう一つの重要な属性は、その「misfire instruction(コマンドがトリガーされていない)」です.schedulerが閉じられたために永続的なトリガがトリガ時間を「逃した」場合、トリガなしで発生します.異なるタイプのトリガには、異なる未トリガ命令があります.デフォルトでは、トリガのタイプや構成に応じて異なるアクションを生成する「スマートポリシー」コマンドが使用されます.schedulerが開始されると、トリガされていないすべての永続triggersが検索され、各トリガによって構成されたトリガされていない命令に従って更新されます.
プロジェクト開始時にQuartzを使用する場合は、各タイプのトリガに定義された未トリガ命令を熟知する必要があります.トリガされていない命令情報の詳細については、各特定のタイプのトリガのガイドコースで説明します.MisfireInstructionプロパティを使用して、指定されたトリガインスタンスに対して非トリガ命令を構成できます.
TriggerUtils-Triggers Made Easy(TriggerUtils)
TriggerUtilsクラスには、トリガと日付を作成する便利な方法が含まれています.このクラスを使用すると、トリガを毎分、時間、日、曜日、月などに簡単にトリガーできます.このクラスを使用すると、トリガに最も近い妙、分、または時間を生成することもでき、トリガ開始時間の設定に非常に役立ちます.
TriggerListeners TriggerListenerインタフェースを実装するオブジェクトは、トリガがトリガーされるという通知を受け取ることができる.
5. SimpleTrigger
SimpleTriggerは、タスクをある時点で1回のみ実行するか、ある時点で開始し、ある時間間隔で繰り返し実行し、ある時点で終了させる.SimpleTriggerには、開始時間、終了時間、繰返し回数、繰返し間隔などの属性が含まれます.このプロパティはすべて、end-timeプロパティにいくつかのエントリが関連付けられていることを期待しています.
SimpleTriggerにはいくつかの異なる構造関数があります.次に、この結果の構造関数を見てみましょう.
 
public SimpleTrigger(String name, String group,Date startTime,Date endTime,int repeatCount,long repeatInterval)

SimpleTrigger Example 1 - Create a trigger that fires exactly once, ten seconds from now
long startTime = System.currentTimeMillis() + 10000L;
SimpleTrigger trigger = new SimpleTrigger("myTrigger", null,new Date(startTime),null,0,0L);

SimpleTrigger Example 2 - Create a trigger that fires immediately, then repeats every 60 seconds, forever
SimpleTrigger trigger = new SimpleTrigger("myTrigger", null, new Date(),null,SimpleTrigger.REPEAT_INDEFINITELY,60L * 1000L);

SimpleTrigger Example 3 - Create a trigger that fires immediately, then repeats every 10 seconds until 40 seconds from now
long endTime = System.currentTimeMillis() + 40000L;
SimpleTrigger trigger = new SimpleTrigger("myTrigger","myGroup", new Date(),new Date(endTime), SimpleTrigger.REPEAT_INDEFINITELY,10L * 1000L);

SimpleTrigger Example 4 - Create a trigger that fires on March 17 of the year 2002 at precisely 10:30 am, and repeats 5 times (for a total of 6 firings) - with a 30 second delay between each firing
java.util.Calendar cal = new java.util.GregorianCalendar(2002, cal.MARCH, 17);
cal.set(cal.HOUR, 10);
cal.set(cal.MINUTE, 30);
cal.set(cal.SECOND, 0);
cal.set(cal.MILLISECOND, 0);

Data startTime = cal.getTime()

SimpleTrigger trigger = new SimpleTrigger("myTrigger", null, startTime,null,5,30L * 1000L);

 
6.実行可能なQuartz.
ContextListenerのinitでは、すべてのジョブの構成をロードし、これらの構成に従って対応するジョブを呼び出します.同時にStatefulJobを使用してJobの状態{またはデータベースに格納}を保存できます.
現在のすべてのジョブのステータスを表示し、restartまたはdestoryのジョブを別の方法で表示できるアクションとページを作成します.