Heim  >  Artikel  >  Java  >  Eingehende Analyse von Quartz's Job und JobDetail

Eingehende Analyse von Quartz's Job und JobDetail

怪我咯
怪我咯Original
2017-07-02 10:43:202377Durchsuche

Der folgende Editor bietet Ihnen eine ausführliche Analyse von Job und JobDetail in Quartz. Der Herausgeber findet es ziemlich gut, deshalb teile ich es jetzt mit Ihnen und gebe es als Referenz. Folgen wir dem Herausgeber und werfen wir einen Blick darauf

Wofür kann Quarz verwendet werden?

Quartz ist ein Framework zur Aufgabenplanung. Wenn Sie beispielsweise auf ein solches Problem stoßen

Sie möchten Ihre Kreditkarte am 25. eines jeden Monats automatisch zurückzahlen

Sie möchten eine Nachricht senden an die Göttin, die du jedes Jahr am 1. April insgeheim geliebt hast. Eine anonyme Grußkarte

Ich möchte meine Liebes-Actionfilm-Studiennotizen stündlich auf der Cloud-Festplatte sichern

Die Zusammenfassung dieser Fragen lautet: Tun Sie regelmäßig etwas. Und die Zeitauslösebedingungen können sehr komplex sein (z. B. 17:50 Uhr am letzten Arbeitstag eines jeden Monats), so komplex, dass hierfür ein spezieller Rahmen erforderlich ist. Quarz ist hier, um so etwas zu tun. Sie geben ihm eine Definition einer Auslösebedingung und er ist dafür verantwortlich, dass der entsprechende Job zu diesem Zeitpunkt ausgeführt wird.

Kein Unsinn mehr, der Code ist großartig. . .

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-Klasse

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-Paket:

Dieses Beispiel deckt die drei wichtigsten Grundelemente von Quartz sehr gut ab:

Scheduler: Scheduler. Die gesamte Terminplanung wird dadurch gesteuert.

Trigger: Definieren Sie die Bedingungen für die Auslösung. Im Beispiel ist sein Typ SimpleTrigger, der alle 1 Sekunde ausgeführt wird (was SimpleTrigger ist, wird weiter unten ausführlich beschrieben).

JobDetail & Job: JobDetail definiert Aufgabendaten und die eigentliche Ausführungslogik befindet sich im Job, im Beispiel ist es HelloQuartz. Warum ist es als JobDetail + Job konzipiert, anstatt Job direkt zu verwenden? Dies liegt daran, dass Aufgaben möglicherweise gleichzeitig ausgeführt werden. Wenn der Scheduler den Job direkt verwendet, besteht das Problem des gleichzeitigen Zugriffs auf dieselbe Jobinstanz. In der JobDetail- und Job-Methode wird bei jeder Ausführung von Sheduler eine neue Job-Instanz basierend auf JobDetail erstellt, sodass das Problem des gleichzeitigen Zugriffs vermieden werden kann.

Scheduler

Scheduler ist das Gehirn von Quartz und alle Aufgaben werden von ihm implementiert.

Schduelr enthält zwei wichtige Komponenten: JobStore und ThreadPool.

JobStore speichert Laufzeitinformationen, einschließlich Trigger, Scheduler, JobDetail, Geschäftssperre usw. Es verfügt über mehrere Implementierungen: RAMJob (Speicherimplementierung), JobStoreTX (JDBC, Transaktionen werden von Quartz verwaltet), JobStoreCMT (JDBC, unter Verwendung von Containertransaktionen), ClusteredJobStore (Cluster-Implementierung) und TerracottaJobStore (was ist Terraractta).

ThreadPool ist ein Thread-Pool und Quartz verfügt über eine eigene Thread-Pool-Implementierung. Alle Aufgaben werden vom Thread-Pool ausgeführt.

SchedulerFactory

SchdulerFactory wird, wie der Name schon sagt, zum Erstellen von Schduler verwendet. Es gibt zwei Implementierungen: DirectSchdulerFactory und StdSchdulerFactory. Ersteres kann verwendet werden, um Ihre eigenen Schduler-Parameter im Code anzupassen. Letzterer liest direkt die quartz.properties-Konfiguration unter dem Klassenpfad (falls nicht vorhanden, verwenden Sie den Standardwert ), um Schduler zu instanziieren. Im Allgemeinen reicht es für uns aus, StdSchdulerFactory zu verwenden.

SchdulerFactory selbst unterstützt die Erstellung von RMI-Stubs, die zur Verwaltung von Remote-Schedulern verwendet werden können. Die Funktionen sind die gleichen wie bei lokalen, und Jobs können remote übermittelt werden.

1.job

Implementierungsklasse 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-Klasse Die Definition von

*/
public class RemindJob implements Job {
private RemindService service=new RemindService();
  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    service.printPlan("你好!");
    
    Date date=new Date();
    String time = date.toString();
    System.out.println(time+"job is starting");
  }


zeigt, dass wir eine JobDetail-Instanz an den Scheduler übergeben, da wir beim Erstellen von JobDetail den Klassennamen des auszuführenden Jobs übergeben zu JobDetail , damit der Scheduler weiß, welche Art von Job er ausführen muss; Wird verworfen, wird die Instanz durch Garbage Collection erfasst. Eine Konsequenz dieser Ausführungsstrategie ist, dass der Job einen parameterlosen

-Konstruktor haben muss (bei Verwendung der Standard-JobFactory ist eine weitere Konsequenz: In einer Jobklasse); Zustandsbehaftete Dateneigenschaften sollten nicht definiert werden, da die Werte dieser Eigenschaften nicht über mehrere Ausführungen des Jobs hinweg beibehalten werden.

Wie fügt man also Attribute oder Konfigurationen zur Jobinstanz hinzu? Wie kann der Status eines Jobs bei mehreren Ausführungen des Jobs verfolgt werden? Die Antwort lautet: JobDataMap, Teil des JobDetail

-Objekts.

JobDataMap

JobDataMap kann unbegrenzte (serialisierte) Datenobjekte enthalten und die Daten können verwendet werden, wenn die Jobinstanz ausgeführt wird. JobDataMap ist eine Java-Implementierung der Map Schnittstelle, die einige zusätzliche Methoden hinzufügt, um den Zugriff auf grundlegende Datentypen zu erleichtern.

将job加入到scheduler之前,在构建JobDetail时,可以将数据放入JobDataMap,如下示例:

JobDetail job=JobBuilder.newJob(RemindJob.class)
      .withIdentity("job1", "group1")
      .usingJobData("hello", "we are family")
      .build();

在job的执行过程中,可以从JobDataMap中取出数据,如下示例:

@Override
  public 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);
    
    Date date=new Date();
    String time = date.toString();
    System.out.println(time+"job is starting");
  }

如果你使用的是持久化的存储机制(本教程的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:

@Override
  public 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);

Das obige ist der detaillierte Inhalt vonEingehende Analyse von Quartz's Job und JobDetail. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn