Остановка задания Quartz, созданного с помощью MethodInvokingJobDetailFactoryBean

я создаю задание, запускающее класс bean-компонента Spring с этим кодом



  MethodInvokingJobDetailFactoryBeanjobDetail = new MethodInvokingJobDetailFactoryBean();
        Class<?> businessClass = Class.forName(task.getBusinessClassType());
        jobDetail.setTargetObject(applicationContext.getBean(businessClass));
        jobDetail.setTargetMethod(task.getBusinessMethod());
        jobDetail.setName(task.getCode());
        jobDetail.setGroup(task.getGroup().getCode());
        jobDetail.setConcurrent(false);

        Object[] argumentArray = builArgumentArray(task.getBusinessMethodParams());
        jobDetail.setArguments(argumentArray);

        jobDetail.afterPropertiesSet();

        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getCode() + "_TRIGGER", task.getGroup().getCode() + "_TRIGGER_GROUP")
                      .withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression())).build();

        dataSchedulazione = scheduler.scheduleJob((JobDetail) jobDetail.getObject(), trigger);
        scheduler.start();

иногда задача перестает отвечать, если я удаляю триггер, а задача из планировщика остается в
List ob = scheduler.getCurrentlyExecutingJobs();

Триггер находится в состоянии NONE, но все еще находится в scheduler.getCurrentlyExecutingJobs();

Я попытался внедрить InterruptableJob в класс, который расширяет MethodInvokingJobDetailFactoryBeanjobDetail.

Но когда я использую

scheduler.interrupt(jobKey);

В нем говорится, что InterruptableJob не реализован. Я думаю, потому что экземпляр класса — это MethodInvokingJobDetailFactoryBeanjobDetail.

`scheduler.scheduleJob((JobDetail) jobDetail.getObject(), trigger);`

это код внутри кварцевого планировщика

`job = jec.getJobInstance();
                if (job instanceof InterruptableJob) {
                    ((InterruptableJob)job).interrupt();
                    interrupted = true;
                } else {
                    throw new UnableToInterruptJobException(
                            "Job " + jobDetail.getKey() +
                            " can not be interrupted, since it does not implement " +                        
                            InterruptableJob.class.getName());
                }
`

Есть ли другой способ убить одну задачу?

Я использую Quartz 2.1.7 и java 1.6 и java 1.8

ТИА

Андреа


person Andreanta    schedule 13.06.2020    source источник


Ответы (1)


Не существует волшебного способа заставить JVM остановить выполнение какой-либо части кода.

Вы можете реализовать различные способы прерывания задания. Но наиболее подходящим способом является реализация InterruptableJob.

Реализации этого интерфейса недостаточно. Вы должны реализовать работу таким образом, чтобы она действительно реагировала на такие запросы.

Пример

Предположим, ваша работа обрабатывает 1 000 000 записей в базе данных или в файле, и это занимает относительно много времени, скажем, 1 час. Тогда одной из возможных реализаций может быть следующая. В методе «interrupt()» вы устанавливаете какой-либо флаг (переменную-член) в значение «true», назовите его isInterruptionRequested. В основной логической части, которая обрабатывает 1 000 000 записей, вы можете регулярно, например. каждые 5 секунд или после каждых, скажем, 100 записей проверяйте, установлен ли для этого флага isInterruptionRequested значение «true». Если установлено, вы выходите из метода, в котором вы реализовали основную логику.

Важно, чтобы вы не проверяли условие слишком часто. В противном случае, в зависимости от логики, может случиться так, что проверка того, было ли запрошено прерывание задания, может занять 80-90% ЦП, намного больше, чем реальная логика :)

Таким образом, даже если вы правильно реализуете интерфейс InterruptableJob, это не означает, что задание будет немедленно остановлено. Это будет просто подсказка типа «Я хотел бы остановить эту работу, когда это будет возможно». Когда он будет остановлен (если вообще) зависит от того, как вы его реализуете.

person mentallurg    schedule 13.06.2020
comment
Спасибо, моя проблема состоит в том, чтобы удалить сиротскую задачу. Иногда задача зависает без исключения и остается в планировщике, и в этом случае я не могу ее убить или прервать. Я пытался реализовать прерываемый интерфейс, но задание построено с помощью Spring MethodInvokingJobDetailFactoryBeanjobDetail, а объект результата не имеет этого интерфейса. - person Andreanta; 13.06.2020