1

Quartz 2 文档清楚地设置了 SimpleJobDetail,以便通过设置 concurrent = false 来执行序列化(即下一个作业在当前作业完成后运行)。Quartz 2 文档也清楚地说明了如何设置作业以使用 InvokeMethodJob 调用 spring bean 方法。但不清楚的是如何将 InvokeMethodJob 设置为仅运行序列化 (concurrent=false)。我在 conf/Config.groovy 中像这样设置 InvokeMethodJob:

import static org.quartz.JobBuilder.*
import static org.quartz.SimpleScheduleBuilder.*
import static org.quartz.TriggerBuilder.*
import org.quartz.impl.triggers.*
import org.quartz.JobDataMap
import org.quartz.JobDetail
import org.quartz.Trigger
import grails.plugin.quartz2.InvokeMethodJob
//Begin quartz configuration
grails.plugin.quartz2.autoStartup = true
    org{
        quartz{
            scheduler.instanceName = 'MyScheduler'
    threadPool.class = 'org.quartz.simpl.SimpleThreadPool'
    threadPool.threadCount = 20
    threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
            jobStore.class = 'org.quartz.simpl.RAMJobStore'
        }
    }
grails.plugin.quartz2.jobSetup.mySchedule = { quartzScheduler, ctx  ->
    def props = new JobDataMap([concurrent:false,targetObject:ctx.myActionService,targetMethod:'myaction',arguments:[true]])
    JobDetail jobDetail = newJob(InvokeMethodJob.class)
        .withIdentity("perform my action")
        .usingJobData(props)
        .build()
    Trigger trigger = newTrigger().withIdentity("every 90 seconds trigger")
        .withSchedule(
            simpleSchedule().withIntervalInSeconds(90).repeatForever()
        )
        .startNow().build()
    quartzScheduler.scheduleJob(jobDetail, trigger)
}

但是,这将允许多个线程同时执行 myActionService.myaction() 调用。我希望调度程序停止对它的进一步调用,直到第一个调用返回。

我阅读了有关@DisallowConcurrentExecution 的信息,但没有办法在conf/Config.groovy 的定义中应用它(或如何应用它的示例)。

我可以设计的最佳解决方案是创建一个新的 Groovy 类扩展 InvokeMethodJob 并使用 @DisallowConcurrentExecution 进行注释,如下所示:

package com.fourgablesguy.quartz2

import grails.plugin.quartz2.InvokeMethodJob
import org.quartz.DisallowConcurrentExecution

/**
 * InvokeMethodJob that is not concurrently executed, serial execution
 * this has the DisallowConcurrentExecution annotation
 */
@DisallowConcurrentExecution
class SerializedInvokeMethodJob extends InvokeMethodJob { }

然后更改 conf/Config.groovy 以使用这个新的 Job 类类型:

import com.fourgablesguy.quartz2.SerializedInvokeMethodJob
...
JobDetail jobDetail = newJob(SerializedInvokeMethodJob.class)

但是我可能错过了一些不太复杂的事情,可以使用石英 2 来完成相同的任务,所以如果有人有不同的解决方案,我会发布这个。

4

1 回答 1

2

问题中描述了我找到的最佳解决方案,使用 @DisallowConcurrentExecution 注释自定义 InvokeMethodJob 类

如果您的系统只执行一项任务,则 threadCount = 1 可能是一个选项。如果您有多个不同的作业,则需要更高的线程数,以便它们可以并行运行(您可能希望某些作业是非并发的。)一旦线程数高于 1,则不能保证非并发执行对于任何工作。

于 2013-07-22T22:23:51.640 回答