about jobs
TRANSCRIPT
About Jobs
Who?
s_kozake(小酒信一)
I’m Java Programmer
こんな心意気で頑張っております
Javaは亡びぬ何度でも蘇るさ!!Javaは亡びぬ何度でも蘇るさ!!
JVMの力こそプログラマーの夢だからね。。誰だ?今「バルス」とかいった奴
About Jobs
の話じゃありません
Playにジョブ管理機能があるのご存知でした?
Playのジョブ管理は結構便利です!!
起動時に実行するジョブpackage jobs;
import play.*;import play.jobs.*; @OnApplicationStartpublic class Bootstrap extends Job { public void doJob() { Logger.info("=== Application start ==="); } }
@OnApplicationStart(async=true)
とすると、バックグラウンドで実行できます
スケジューリングされたジョブ
package jobs;
import play.*;import play.jobs.*; @Every("10s")public class EveryTenSeconds extends Job { private int count = 0; public void doJob() { count++; Logger.info("=== EveryTenSeconds execute " + count + "time" + (count > 1 ? "s" : "")); } }
10日毎 ・・・ @Every("10d")10時間毎 ・・ @Every("10h")10分毎 ・・・ @Every("10mn") or @Every("10min")10秒毎 ・・・ @Every("10s")
PlayはCRON式もサポートしています。
CRON式でスケジュールされたジョブ
package jobs;
import play.*;import play.jobs.*;import java.util.Calendar; @On("2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59 * * * * ?")public class EveryPrimeNumber extends Job {
public void doJob() { Logger.info("=== Every prime sec " + Calendar.getInstance().get(Calendar.SECOND) + " execute " ); } }
* * * * * ? *秒
(0-59 *)時間(0-23 *)
日(1-31 * ?)
月(1-12 * ?)
or(JAN-DEC)
曜日(1-7 * ?)
or(SUN-SAT)
年(1970-2099 *)
[option]
分(0-59 *)
CRON式(基本)
@On(“ 2 * * * * ?”)・・・毎分2秒に実行@On(“ 0 0 * * * ?”)・・・毎時0分に実行@On(“30 59 23 * * ?”)・・・毎日23:59:30秒に実行@On(“30 59 23 ? * 2”)・・・毎金曜日の23:59:30秒に実行
CRON式(応用)
@On(“0,30 * * * * ?”)・・・毎分0,30秒に実行@On(“30 10-20 * * * ?”)・・毎時10~20分の間、30秒に実行@On(“5/15 * * * * ?”)・・・毎分5秒から15秒毎(5,20,35,50)に実行
各項目には(, - /)を指定できます。
CRON式(さらなる応用)
日のLは月の最終日。曜日のLは月の最後の曜日。@On(“0 23 59 L * ?”)・・・毎月の最終日(1月なら31日、4月なら30日)の23:59:00に実行@On(“0 23 59 ? * 6L”)・・・毎月の最後の土曜日に実行
日のWは一番近い月~金曜日。例えば、15Wは15日が土曜日なら、14日の金曜日に実行。15日が日曜日なら16日の月曜日に実行。15日が火曜日なら、15日火曜日に実行。1Wは1日が土曜日なら、3日の月曜日に実行
曜日の#は月の何番目の曜日か。例えば、6#3は月の3回目の金曜日。
日には(L W)、曜日には(L #)を指定できます。
CRON式を環境変数に記述可能package jobs;
import play.*;import play.jobs.*;import java.util.Calendar; @On("cron.everyprimenumber")public class EveryPrimeNumber extends Job { :
cron.everyprimenumber=2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59 * * * * ?#cron.everyprimenumber=never
application.conf
“cron.”で始まるものは環境変数と認識される
neverを設定すると、実行されませんよ
トリガータスクジョブ
public static void encodeVideo(Long videoId) { new VideoEncoder(videoId).now(); renderText("Encoding started");}
nowメソッドで即時実行できます。戻り値は予約オブジェクトで受け取れます。
NOTE
DEV モードでアプリケーションを実行する場合、アプリケーションは最初の HTTP リクエストがあるまで始動を控えます。さらには、DEV モードの場合、アプリケーションは必要に応じて自動的に再起動することがあります。
PROD モードで実行するとき、アプリケーションはサーバの起動と同時に開始します。
実演
Inside of Play.jobs
@EveryはScheduledThreadPoolExecutorのscheduleWithFixedDelayメソッドで実現している。
@Onはタスク終了後にcron式の次の日付を求めて、 duledThreadPoolExecutorのscheduleメソッドを毎回読んでいる。
play.jobsはjava.util.concurrentの機能を色々使ってて、勉強になるお
About cron4j
cron4jってご存知ですか?
Javaでunixのcrontabを使えます!
MyTask.java
public class MyTask implements Runnable {
public void run() {
System.out.println("Current system time: " + new Date());
System.out.println("Another minute ticked away...");
}
}
Quick Start
タスクを書いて。。
public class Main {
public static void main(String[] args) {
MyTask task = new MyTask();
Scheduler scheduler = new Scheduler();
scheduler.schedule("* * * * *", task);
scheduler.start();
try {
Thread.sleep(5L * 60L * 1000L);
} catch (InterruptedException e) {
;
}
scheduler.stop();
}
}
Main.java
スケジューラを起動するだけ。。
ファイルも扱えます
public class Main {
public static void main(String[] args) {
Scheduler scheduler = new Scheduler();
scheduler.scheduleFile("* * * * *", new File("cron4jtab.txt");
scheduler.start();
:
Main.java
こんな感じ
0 5 * * * sol.exe
0,30 * * * * OUT:C:\ping.txt ping 10.9.43.55
0,46 * * * * "OUT:C:\My Folder With Spaces\ping.txt" ping 10.9.43.55
0 3 * * * ENV:JAVA_HOME=C:\jdks\1.4.2_15 DIR:C:\myproject OUT:C:\myproject\build.log C:\myproject\build.bat "Nightly Build"
0 1 * * * java:test.TestClass#testMethod "Iron Maiden" "Megadeth" "Black Sabbath" "Led Zeppelin" "Blind Guardian"
cron4jtab.txt
ファイルの中身。Javaメソッド単位で起動することも、外部プロセスを起動することも可能。Javaの場合、class#method の形式のメソッドを呼び出し可能メソッドはstaticでString配列をパラメータで受け取れること。記述を省いた場合、main(String[] args)が呼ばれます。
外部プロセスを呼び出す場合、 OUT・・標準出力 IN・・・・標準入力 ENV・・環境設定 DIR・・・作業フォルダが指定可能です。
ファイルの中身はスケジューラ実行中にも変更可能&反映されます。
Taskの状態を制御したり、監視したりできます。
public class MyTaskExecutorListener implements TaskExecutorListener {
public void executionPausing(TaskExecutor executor) {
System.out.println("Task pausing!");
}
public void executionResuming(TaskExecutor executor) {
System.out.println("Task resuming!");
}
public void executionStopping(TaskExecutor executor) {
System.out.println("Task stopping!");
}
public void executionTerminated(TaskExecutor executor, Throwable exception) {
System.out.println("Task terminated!");
}
public void statusMessageChanged(TaskExecutor executor, String statusMessage) {
System.out.println("Task statusMessage = ["+statusMessage+"]");
}
public void completenessValueChanged(TaskExecutor executor, double completenessValue) {
System.out.println("Task completeness["+completenessValue * 100+"]%");
}
}
MyTaskExecutionListener.java
import it.sauronsoftware.cron4j.SchedulerListener;
import it.sauronsoftware.cron4j.TaskExecutor;
public class MySchedulerListener implements SchedulerListener {
public void taskLaunching(TaskExecutor executor) {
System.out.println("Task launched!");
executor.addTaskExecutorListener(new MyTaskExecutorListener());
}
public void taskSucceeded(TaskExecutor executor) {
System.out.println("Task completed!");
}
public void taskFailed(TaskExecutor executor, Throwable exception) {
System.out.println("Task failed due to an exception!");
exception.printStackTrace();
}
}
MySchedulerListener.java
import it.sauronsoftware.cron4j.Scheduler;
public class Main {
public static void main(String[] args) {
MySchedulerListener listener = new MySchedulerListener();
MyTask task = new MyTask();
Scheduler scheduler = new Scheduler();
scheduler.addSchedulerListener(listener);
:
}
}
Main.java
import it.sauronsoftware.cron4j.Task;
import it.sauronsoftware.cron4j.TaskExecutionContext;
public class MyTask extends Task {
public boolean canBePaused() { return true; }
public boolean canBeStopped() { return true; }
public boolean supportsCompletenessTracking() { return true; }
public boolean supportsStatusTracking() { return true; }
public void execute(TaskExecutionContext context) throws RuntimeException {
for (int i = 1; i <= 30; i++) {
System.out.println("Task says: " + i);
context.setStatusMessage("i = " + i);
context.setCompleteness(i / 30D);
try {
Thread.sleep(1000);
} catch (InterruptedException e) { ; }
context.pauseIfRequested();
if (context.isStopped()) {
break;
}
}
}
}
MyTask.java
Taskの状況メッセージを設定
Taskの進捗を設定
ポーズ要求がある場合はwait
停止要求がある場合は終了
ジョブの画面制御も簡単
・スケジュールは分単位まで
play.jobsとちゃうとこ
・前のタスクが終わらんでも、次が動く
・タスクは毎回newされるから、状態もてない
・Java2から使える
Thank You!