Quartz はタスク スケジューリング フレームワークです。たとえば、こんな問題に遭遇したら
毎月25日にクレジットカードに自動返済してもらいたい
毎年4月1日に好きな女神に匿名のグリーティングカードを送りたい
ラブ アクション映画の学習ノートを 1 時間ごとにクラウド ディスクにバックアップしたいです
これらの質問の要約は、次のとおりです。定期的に何かをする。また、時間トリガー条件は非常に複雑になる場合があります (毎月の最終営業日の 17:50 など)。これを行うには特別なフレームワークが必要になるほど複雑です。 Quartz はこのようなことを行うためにあります。トリガー条件の定義を与えると、その時点で対応するジョブが動作するようにトリガーされます。
これ以上ナンセンスはありません。コードは素晴らしいです。 。 。
public static void main(String[] args) { try { //创建scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); //定义一个Trigger Trigger trigger =TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") //定义name/group.startNow()//一旦加入scheduler,立即生效. withSchedule(SimpleScheduleBuilder.simpleSchedule() //使用SimpleTrigger.withIntervalInSeconds(1) //每隔一秒执行一次.repeatForever()) //一直执行 .build(); //定义一个JobDetail JobDetail job =JobBuilder.newJob(HelloQuartz.class) //定义Job类为HelloQuartz类,这是真正的执行逻辑所在.withIdentity("job1", "group1") //定义name/group.usingJobData("name", "quartz") //定义属性 .build(); //加入这个调度 scheduler.scheduleJob(job, trigger); //启动之 scheduler.start(); //运行一段时间后关闭 Thread.sleep(10000); scheduler.shutdown(true); } catch (Exception e) { e.printStackTrace(); } }
HelloQuartz类
public class HelloQuartz implements Job {public void execute(JobExecutionContext context) throws JobExecutionException { JobDetail detail = context.getJobDetail(); String name = detail.getJobDataMap().getString("name"); System.out.println("say hello to " + name + " at " + new Date()); } }
jar パッケージ:
この例では、Quartz の 3 つの最も重要な基本要素をよくカバーしています:
Scheduler: スケジューラー。すべてのスケジュールはそれによって制御されます。
トリガー: トリガーの条件を定義します。この例では、そのタイプは SimpleTrigger で、1 秒ごとに実行されます (SimpleTrigger については後で詳しく説明します)。
JobDetail と Job: JobDetail はタスク データを定義し、実際の実行ロジックはジョブ内にあります。この例では、HelloQuartz です。 Job を直接使用するのではなく、JobDetail + Job として設計されているのはなぜですか?これは、スケジューラがジョブを直接使用する場合、タスクが同時に実行される可能性があるため、同じジョブ インスタンスへの同時アクセスの問題が発生する可能性があります。 JobDetail & Jobメソッドでは、スケジューラが実行されるたびにJobDetailを元に新しいJobインスタンスが作成されるため、同時アクセスの問題を回避できます。
スケジューラはQuartzの頭脳であり、すべてのタスクはそれによって実装されます。
Schduelr には、JobStore と ThreadPool という 2 つの重要なコンポーネントが含まれています。
JobStore には、トリガー、スケジューラー、JobDetail、ビジネス ロックなどの実行時情報が保存されます。 RAMJob(メモリ実装)、JobStoreTX(JDBC、トランザクションはQuartzで管理)、JobStoreCMT(JDBC、コンテナトランザクションを使用)、ClusteredJobStore(クラスタ実装)、TerracottaJobStore(Terraracttaとは)という複数の実装があります。
ThreadPool はスレッド プールであり、Quartz には独自のスレッド プール実装があります。すべてのタスクはスレッド プールによって実行されます。
SchdulerFactory は、名前が示すように、Schduler を作成するために使用されます。DirectSchedulerFactory と StdSchdulerFactory の 2 つの実装があります。前者は、コード内で独自の Schduler パラメーターをカスタマイズするために使用できます。後者は、クラスパスの下のquartz.properties設定を直接読み取り(存在しない場合はデフォルト値を使用します)、Schdulerをインスタンス化します。一般的に言えば、StdSchdulerFactory を使用するだけで十分です。
SchdulerFactory 自体は、リモート スケジューラーの管理に使用できる RMI スタブの作成をサポートしています。機能はローカルのスケジューラーと同じであり、ジョブをリモートで送信できます。
1.job
実装クラス JobDetail
JobDetail job = JobBuilder.newJob(RemindJob.class) .withIdentity("job1", "group1").build();//创建一个任务 /** * 创建触发器 * 第一种方式 不太好 */SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger", "myTriggerGroup"). withSchedule(SimpleScheduleBuilder.simpleSchedule(). withIntervalInSeconds(3). repeatForever()). startAt(new Date(System.currentTimeMillis()+1000)).build(); /** * 创建触发器 * 第二种 方式 非常好 * 可以 好用 2013年每月的第三个星期五上午10:30触发 0 30 10 ? * 6#3 2013 * 2016年每月的第一个星期四下午16:17触发 0 17 16 ? * 5#1 2016 * 每天15点到16点每5分钟运行一次,此外,每天17点到18点每5分钟运行一次 *//*CronTrigger trigger=TriggerBuilder.newTrigger() .withIdentity("myTrigger", "myTriggerGroup") .withSchedule(CronScheduleBuilder.cronSchedule("0 18 16 ? * 5#1 2016")).build();*/ SchedulerFactory sf=new StdSchedulerFactory();//创建调度者工厂Scheduler scheduler = sf.getScheduler();//创建一个调度者scheduler.scheduleJob(job,trigger);//注册并进行调度scheduler.start();//启动调度 //Thread.sleep(millis) //scheduler.shutdown();//关闭调度
RemindJob 类的定义
*/public class RemindJob implements Job {private RemindService service=new RemindService(); @Overridepublic void execute(JobExecutionContext context) throws JobExecutionException { service.printPlan("你好!"); Date date=new Date(); String time = date.toString(); System.out.println(time+"job is starting"); }
JobDetail インスタンスをスケジューラに渡していることがわかります。これは、JobDetail を作成するときに、ジョブがクラス名が JobDetail に渡されるため、スケジューラはジョブを実行するたびに、実行後に use(...) メソッドを呼び出す前にクラスの新しいインスタンスが作成されます。インスタンスへの参照は破棄され、インスタンスはガベージ コレクションされます。この実行戦略の 1 つの結果として、ジョブにはパラメーターのないコンストラクターが必要になります (デフォルトの JobFactory を使用する場合)。また、ジョブ クラスではステートフルになります。これらのプロパティの値はジョブの複数の実行にわたって保持されないため、データ プロパティは定義しないでください。
では、ジョブ インスタンスに属性や設定を追加するにはどうすればよいでしょうか?ジョブの複数の実行中にジョブのステータスを追跡するにはどうすればよいですか?答えは、JobDataMap、JobDetail オブジェクトの一部です。
JobDataMap には無制限の (シリアル化された) データ オブジェクトを含めることができ、そのデータはジョブ インスタンスの実行時に使用できます。JobDataMap は、簡単にアクセスできるデータ型のメソッドをいくつか備えた Java Map インターフェイスの実装です。 。
ジョブをスケジューラに追加する前に、JobDetail を構築するときに、次の例のようにデータを JobDataMap に入れることができます:
JobDetail job=JobBuilder.newJob(RemindJob.class) .withIdentity("job1", "group1") .usingJobData("hello", "we are family") .build();
ジョブの実行中に、データを取り出すことができます次の例のように、JobDataMap の
如果你使用的是持久化的存储机制(本教程的JobStore部分会讲到),在决定JobDataMap中存放什么数据的时候需要小心,因为JobDataMap中存储的对象都会被序列化,因此很可能会导致类的版本不一致的问题;Java的标准类型都很安全,如果你已经有了一个类的序列化后的实例,某个时候,别人修改了该类的定义,此时你需要确保对类的修改没有破坏兼容性;更多细节,参考现实中的序列化问题。另外,你也可以配置JDBC-JobStore和JobDataMap,使得map中仅允许存储基本类型和String类型的数据,这样可以避免后续的序列化问题。
如果你在job类中,为JobDataMap中存储的数据的key增加set方法(如在上面示例中,增加setJobSays(String val)方法),那么Quartz的默认JobFactory实现在job被实例化的时候会自动调用这些set方法,这样你就不需要在execute()方法中显式地从map中取数据了。
在Job执行时,JobExecutionContext中的JobDataMap为我们提供了很多的便利。它是JobDetail中的JobDataMap和Trigger中的JobDataMap的并集,但是如果存在相同的数据,则后者会覆盖前者的值。
下面的示例,在job执行时,从JobExecutionContext中获取合并后的JobDataMap:
@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException { service.printPlan("你好!"); JobKey key=context.getJobDetail().getKey(); /* JobDataMap map = context.getJobDetail().getJobDataMap(); String string = map.getString("hello"); System.out.println(key+"==========="+string);*/ JobDataMap map = context.getMergedJobDataMap(); String string = map.getString("hello"); System.out.println(key+"--------------------- "+string);
以上がクォーツは何に使えますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。