クォーツソースコード分析(上)
Quartz Source Code Analysis
記事のディレクトリ
アイデア
Quartzフレームワークは、最近のプロジェクトで使用されています。タイミングタスクのスケジューリングフレームワークとして、Springとの完全な融合であろうと、Javaコードを直接使用するものであろうと、非常にシンプルで安定していると言えます。 ある日、Quartzフレームワークがない場合、純粋なJavaコードを使用して時限タスクスケジューリングフレームワークをどのように実装すればよいのかと突然思いました。
- アイデア1:私はすぐにデザインのアイデアを思いつきました。 現在の時点とタスクの時点を継続的にポーリングするには、個別のスケジューリングスレッドが必要です。タスクの出発時刻に達すると、スレッドが開かれ、引き渡す必要のあるタスクがそのスレッドに送信されます。 。ただし、そうするとスレッドが多すぎる可能性があり、CPUリソースを占有するためにスレッドを継続的に循環させることは合理的ではありません。
- アイデア2:初版のアイデアに基づいて、 別のスケジューリングスレッドは、タスクが次にトリガーされてスリープに入るのを待ちます。スレッドのスリープ時間は、次のトリガーの時間差に応じて決定され、タスクはスレッドプールに送信されます。 タスクが多すぎるために発生するスレッドの爆発現象を回避できます。
だから私はQuartzのソースコードを見るしかありませんでした(もっと釣りをしています...)、そしてQuartzのコアデザインのアイデアが私の2番目のバージョンのアイデアに似ていることがわかりました、そしてナンセンスは大多数ではありません、ソースコードを見せてください!
2.Quartz全体のアーキテクチャ
最初に写真を盗む:
Quartzフレームワークのスリーピースセット:
- ジョブ:実行する必要のあるタスク。
- トリガー:トリガー、ジョブをトリガーする特定の時間を指定できます
- スケジューラー(コア): 統合スケジューラ、ジョブ、トリガーがパラメータとして渡され、スケジューラはタスクのトリガーとタイムスケジューリングを完了します
タスクの送信からタスクのスケジュールされた実行までのQuartzは、これら3つのセットに依存して完了すると言えます。もちろん、Quartzの基本的な使用法をマスターしていると思いますが、これらのコンポーネントを分析します。一つずつ。
2.1ジョブとJobDetail
Quartzでタスクを送信する場合、 自己実装が必要ですJob
インターフェースのクラス。定期的にトリガーされるコードを上書きするだけで済みます。execute
メソッド 。
/ / Class that implements the Job interface public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println('this is a test job!') } }
Quartzを使用する場合、必要なビジネスを完了するためにJobインターフェースを実装しました。execute
メソッドが必要ですJob
インターフェースを実装する必要がある唯一の方法。
実際、Quartzは、ジョブのパッケージ化をより複雑にする必要があります。たとえば、Spring
内部パッケージで生成されますBean
同じJob
最終的にはa JobDetailImpl
にパッケージ化されますオブジェクト。
JobDetailImpl
はいJobDetail
インターフェースのデフォルトの実装クラス。これらのプロパティのいくつかを見ることができます。
JobDetailImpl
オブジェクトはQuartzフレームワークで使用されます。SpringBean
オブジェクトはSpringフレームワークで使用されます。追加Job
パッケージに基づきます。
on JobDetail
オブジェクト生成、Quartz使用 ビルダーモード :
見ることができますJobBuilder
クラスの構造、明らかにこれはa Builder
クラスです。
public JobDetail build() { JobDetailImpl job = new JobDetailImpl() job.setJobClass(jobClass) job.setDescription(description) if(key == null) key = new JobKey(Key.createUniqueName(null), null) job.setKey(key) job.setDurability(durability) job.setRequestsRecovery(shouldRecover) if(!jobDataMap.isEmpty()) job.setJobDataMap(jobDataMap) return job }
**コアメソッドは上記のとおりです。ビルダーモードは、Android側でより一般的に使用されます。ここでの利点は、生成する方が便利なことです。JobDetail
オブジェクト、引き渡されるScheduler
使用。 ** ps: ビルダーモードについて-新人チュートリアル
2.2トリガー
Tigger
トリガーロールとしてのQuartzでは、渡すことができますTrigger
オブジェクトは、タスクスケジューリングの頻度設定、時間設定などを実装するために使用されます。
Trigger
Quartzには2つの一般的な使用法があり、1つはSimpleTrigger
インターフェースによって実装された単純なトリガーに基づいています。これらのトリガールールは比較的単純です。これらは通常、特定の間隔で実行されます。インターフェイスによって実装されたCronTrigger
cron式トリガーに基づく単語もあります。 cron式は、より強力なトリガールールを実装できます。 Quartzの友達は間違いなくCron式にさらされます(Linuxにさらされていたに違いありません) 。ここでは、より単純に見えますSimpleTrigger
Trigger
インスタンスおよびJobDetail
例のように、これらはBuilderパターンを使用して作成されます。実際の実装クラスはSimpleTriggerImpl
classです。
見てみましょうSimpleTrigger
クラス継承図:
実際、トリガーの役割の説明は、QuartzにJavaDocが付属しているので、私が言ったよりも明確なはずです。
/** * A {@link Trigger}
Job
クラスには、トリガー名、グループ、開始時間、実行回数、実行間隔、その他の多くの属性など、多くのプロパティがあります。SimpleTriggerImpl
クラスと同様に、これらのプロパティQuartzフレームワークによって使用されます。
これは、sum JobDetailImpl
密接に関連するクラス、つまりTrigger
Classの特別な説明です。明らかに、これはBuilderモードのクラスでもあります。 実際には、a ScheduleBuilder
使用されるスケジュールを生成し、パラメーターとして渡されますTrigger
クラス内 ここでの注記も非常に明確です。TriggerBuilder
トリガーのトリガー時間を定義するために使用されます。 (もちろんScheduleBuilder
別の変換ロジックのセットです。トウモロコシの式をタイムラインに変換する必要があります)

2.3 JobStore
ここに古典的な質問があります:私は今コーヒーを持っています、ミルクと一緒に、どうすればコーヒーミルクを手に入れることができますか?
はい、カップが必要です。
今と同じようにCronTrigger
持っているJob
、 それらをどのように関連付けて保存しますか? ?答えはTrigger
クラス、 JobStore
確立されているJobStore
with JobDetail
関連付けられたキークラスも保存されているTrigger
with JobDetail
タイプ 。 Quartz内には2つの実装クラスがあります。
- メモリに格納され、対応するクラス
Tigger
このストレージクラスのプロパティは、プロジェクトの再起動後にデータがクリアされることです。 - JDBCインターフェースを使用してデータベースに格納され、対応する
RAMJobStore
ClassおよびJobStoreTX
Classesは、それぞれQuartzスタンドアロン永続性およびクラスター永続性デプロイメントのデータベース操作に対応します。
ここで分析しますJobStoreCMT
このクラスは手動で作成する必要はありません。構成ファイルでデータベース構成が有効になっていない場合、Quartzはデフォルトでこのクラスを使用します。
Quartzフレームワークでは、RAMJobStore
メソッドの送信scheduleJob
with Job
、achieve Trigger
with Job
に関連する2つの重要なステップがあります。
Trigger
インスタンス設定Trigger
ここでは各Quartzフレームワークに注意を払う必要がありますJobKey
一意になりますJob
識別するために - storage
JobKey
with JobDetial
To Trigger
Quartzには、保存する方法が2つあります。1つはメモリに保存され、もう1つは使用されます。JobStore
データベースに保存されます。
以下はJDBC
クラスのコアメソッドRAMJobStore
ソースコード:
storeJobAndTrigger
シンプルで明確、最初に保存public void storeJobAndTrigger(JobDetail newJob, OperableTrigger newTrigger) throws JobPersistenceException { storeJob(newJob, false) storeTrigger(newTrigger, false) }
もう一度保存Job
もちろん、実際にはTrigger
with storeJob
このメソッドは、ストレージオブジェクトメソッドの実際の実装です。
次の質問が来ます。ストレージを設計する場合storeTrigger
with Job
メモリ内の構造を関連性のあるものにしながら、Javaでのどのコンテナ実装を選択しますか? 2年生について考えさせてください。私たちのカリキュラム設計は、SQLタイプのデータベースを実装しています。ネストのいくつかのレイヤーを使用します。Trigger
ストレージ構造を作成しました。 もちろんここHashMap
入れ子RAMJobStore
満たすHashMap
とJob
マッピング関係。
Trigger
そうです、あなたが思うほど簡単です。// core storage container protected Map<JobKey, List<TriggerWrapper>> triggersByJob = new HashMap<JobKey, List<TriggerWrapper>>(1000)
前に述べたように、Quartzフレームワークではグローバルに一意です(分散展開Quartzはグローバルに一意ですが、使用されますJobKey
クラス)、 UUID
はいList
リスト、つまり1つTrigger
複数Job
トリガーに対応できます。
保存方法を見てみましょう。
Trigger
public void storeTrigger(OperableTrigger newTrigger, boolean replaceExisting) throws JobPersistenceException { TriggerWrapper tw = new TriggerWrapper((OperableTrigger)newTrigger.clone()) synchronized (lock) { // ...... omit part of the code // core function code: add to triggers by job List<TriggerWrapper> jobList = triggersByJob.get(tw.jobKey) if(jobList == null) { jobList = new ArrayList<TriggerWrapper>(1) triggersByJob.put(tw.jobKey, jobList) } jobList.add(tw) // ...... part of the code is omitted } }
ここでのキーワードは、マルチスレッド環境でのデータのセキュリティを確保することです。実際、データを保存するだけで非常に簡単ですが、synchronized
後で説明します。JobStore
コアコードは非常に重要な役割を果たします。
3.最初の要約
これまで、Quartzのコア作業コードを分析していません。理解してくださいScheduler
with Job
作成、パッケージ化、保存、もちろん、これも非常に重要です。 ことわざにあるように、賢い女性はご飯なしではいられません。Trigger
with Job
原材料もクォーツの重要な部分であるため、次の記事を分析しますTrigger
出典Quartzのコアコードであるコード スレッドモデル、設計アイデアを含む、いくつかの分析を行います。
Quartzがどのようにそれを実現するかという私たちの考えの1つについては、こちらもご覧ください。 次 。
参考資料:
- https://blog.csdn.net/qq_29166327/article/details/80502310 –クォーツの使用の概要
- http://www.runoob.com/design-pattern/builder-pattern.html –ビルダーモードの概要
- https://www.jianshu.com/p/f466e02e2e94 –この恩赦は、Quartzのソースコード分析でもあります。品質は非常に高く、詳細です。彼が最初にそれを書いたことを私は知っていました、hehe。