Some quartz records and quartz records

Source: Internet
Author: User

Some quartz records and quartz records

Scheduled tasks always run in the case of overlapping tasks. For example, if a task is executed once every minute and the task execution time exceeds one minute, two identical tasks are executed concurrently. Sometimes we allow this situation to happen. For example, the Code executed by a task is idempotent, and sometimes we may consider that it is not allowed to happen in some cases.

In actual scenarios, we use quartz to schedule scheduled tasks. The Business Code of scheduled tasks is distributed in various applications and called using soa.

For quartz, the official document clearly specifies a solution to this requirement, that is, using annotation @ DisallowConcurrentExecution;

Meaning: Prohibit concurrent execution of multiple JobDetail with the same definition, which is what we want.

The following example compares two jobs: AllowConcurrentExecutionTestJob and DisallowConcurrentExecutionTestJob.

Public class AllowConcurrentExecutionTestJob implements Job {public AllowConcurrentExecutionTestJob () {} public void execute (JobExecutionContext context) throws JobExecutionException {try {List <JobExecutionContext> list = context. getScheduler (). getCurrentlyExecutingJobs (); for (JobExecutionContext jobExecutionContext: list) {// get the variable System in the container in the job. out. println (jobExecutionContext. getJobDetail (). GetKey (). getName ();} Thread. sleep (4000);} catch (SchedulerException e) {e. printStackTrace ();} catch (InterruptedException e) {e. printStackTrace ();} System. out. println ("Hello World! AllowConcurrentExecutionTestJob is executing .");}}
@ DisallowConcurrentExecutionpublic class DisallowConcurrentExecutionTestJob implements org. quartz. job {public DisallowConcurrentExecutionTestJob () {} public void execute (JobExecutionContext context) throws JobExecutionException {try {List <JobExecutionContext> list = context. getScheduler (). getCurrentlyExecutingJobs (); for (JobExecutionContext jobExecutionContext: list) {// get the variable System in the container in the job. ou T. println (jobExecutionContext. getJobDetail (). getKey (). getName ();} Thread. sleep (4000);} catch (SchedulerException e) {e. printStackTrace ();} catch (InterruptedException e) {e. printStackTrace ();} System. out. println ("Hello World! DisallowConcurrentExecutionTestJob is executing .");}}

Test code:

public class QuartzTest {    public static void main(String[] args) throws InterruptedException {        try {            // Grab the Scheduler instance from the Factory            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();            // and start it off            scheduler.start();            // define the job and tie it to our HelloJob class            JobDetail job = JobBuilder.newJob(DisallowConcurrentExecutionTestJob.class)                    .withIdentity("job1", "group1")                    .build();            // Trigger the job to run now, and then repeat every 40 seconds            Trigger trigger = TriggerBuilder.newTrigger()                    .withIdentity("trigger1", "group1")                    .startNow()                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()                            .withIntervalInSeconds(1)                            .repeatForever())                    .build();            // define the job and tie it to our HelloJob class            JobDetail job2 = JobBuilder.newJob(AllowConcurrentExecutionTestJob.class)                    .withIdentity("job2", "group1")                    .build();            // Trigger the job to run now, and then repeat every 40 seconds            Trigger trigger2 = TriggerBuilder.newTrigger()                    .withIdentity("trigger2", "group1")                    .startNow()                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()                            .withIntervalInSeconds(1)                            .repeatForever())                    .build();            // Tell quartz to schedule the job using our trigger            scheduler.scheduleJob(job2, trigger2);//            scheduler.scheduleJob(job2, trigger2);            // wait trigger            Thread.sleep(20000);            scheduler.shutdown();        } catch (SchedulerException se) {            se.printStackTrace();        }    }}

 

We also found that the parameter JobExecutionContext is passed in the execute of the job, which allows us to get information about the job being executed. So I want to know whether there are the same jobs that are already being executed in the job.

public class SelfDisAllowConExeTestJob implements org.quartz.Job{    public void execute(JobExecutionContext context) throws JobExecutionException {        try {            List<JobExecutionContext> list = context.getScheduler().getCurrentlyExecutingJobs();            Set<String> jobs = new HashSet<String>();            int i=0;            for (JobExecutionContext jobExecutionContext : list){                if(context.getJobDetail().getKey().getName().equals(jobExecutionContext.getJobDetail().getKey().getName())){                    i++;                }            }            if(i>1){                System.out.printf("self disallow ");                return;            }            Thread.sleep(4000);        } catch (SchedulerException e) {            e.printStackTrace();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("Hello World!  SelfDisAllowConExeTestJob is executing.");    }}

Test code:

public class OuartzSelfMapTest {    public static void main(String[] args) throws InterruptedException {        try {            // Grab the Scheduler instance from the Factory            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();            // and start it off            scheduler.start();            // define the job and tie it to our HelloJob class            JobDetail job = JobBuilder.newJob(SelfDisAllowConExeTestJob.class)                    .withIdentity("job1", "group1")                    .build();            // Trigger the job to run now, and then repeat every 40 seconds            Trigger trigger = TriggerBuilder.newTrigger()                    .withIdentity("trigger1", "group1")                    .startNow()                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()                            .withIntervalInSeconds(1)                            .repeatForever())                    .build();            // Tell quartz to schedule the job using our trigger            scheduler.scheduleJob(job, trigger);            // wait trigger            Thread.sleep(20000);            scheduler.shutdown();        } catch (SchedulerException se) {            se.printStackTrace();        }    }}

In actual code, we often combine spring to take a look at the concurrent attribute of MethodInvokingJobDetailFactoryBean to control whether concurrent execution is restricted:

        Class<?> jobClass = (this.concurrent ? MethodInvokingJob.class : StatefulMethodInvokingJob.class);
    /**     * Extension of the MethodInvokingJob, implementing the StatefulJob interface.     * Quartz checks whether or not jobs are stateful and if so,     * won't let jobs interfere with each other.     */    @PersistJobDataAfterExecution    @DisallowConcurrentExecution    public static class StatefulMethodInvokingJob extends MethodInvokingJob {        // No implementation, just an addition of the tag interface StatefulJob        // in order to allow stateful method invoking jobs.    }

Of course, there is a StatefulJob in quartz, which facilitates direct inheritance and implements concurrent = false.

So I want to say that there is no interface in quartz that can be set to concurrent or not. Instead, it needs to be inherited by a custom job or implemented using annotations.

 

In addition, there is a related annotation: @ PersistJobDataAfterExecution

JobDataMap in JobDetail is shared, that is, information can be transmitted during execution of the same task. It is easy to think that since it is shared, there will be concurrency problems, as in the scenario described at the beginning, it will lead to concurrency problems. Therefore, the official documents also explain that this annotation is best used with @ DisallowConcurrentExecution.

The following is an example:

@PersistJobDataAfterExecutionpublic class PersistJob implements Job {    public void execute(JobExecutionContext context) throws JobExecutionException {        JobDataMap data = context.getJobDetail().getJobDataMap();        int i = data.getInt("P");        System.out.printf("PersistJob=>"+i);        i++;        data.put("P", i);    }}

Test code:

Public class PersistJobDataQuartzTest {public static void main (String [] args) throws InterruptedException {try {// Grab the Scheduler instance from the Factory Scheduler schedfactory = StdSchedulerFactory. getdefaschscheduler (); // and start it off scheduler. start (); JobDataMap jobDataMap = new JobDataMap (); jobDataMap. put ("P", 1); // define the job and tie it to our HelloJob class JobDetail job = JobBuilder. newJob (PersistJob. class ). withIdentity ("job1", "group1 "). usingJobData (jobDataMap ). build (); // Trigger the job to run now, and then repeat every 40 seconds Trigger trigger = TriggerBuilder. newTrigger (). withIdentity ("trigger1", "group1 "). startNow (). withSchedule (SimpleScheduleBuilder. simpleSchedule (). withIntervalInSeconds (1 ). repeatForever ()). build (); // Tell quartz to schedule the job using our trigger scheduler. scheduleJob (job, trigger); // wait trigger Thread. sleep (20000); scheduler. shutdown ();} catch (SchedulerException se) {se. printStackTrace ();}}}View Code

 

Reference:

Https://jayvilalta.com/blog/2014/06/04/understanding-the-disallowconcurrentexecution-job-attribute/http://www.quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/tutorial-lesson-03http://www.cnblogs.com/lnlvinso/p/4194725.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.