首页 > 解决方案 > 2 Quartz 作业同时更新数据库中的相同值导致不一致的行为

问题描述

我有一份石英工作做一些事情,并为一个特定案例花费大量时间,而其他案例则非常快。因此,当一个缓慢的案例运行很长时间并且其他事情完成时,我不想停止我的工作。此作业运行并检查 doStuff 标志。当 doStuff==1 运行时做事情并将值设为 0。因此,当下次触发作业时,它不应该运行已经完成的事情。

所以为了解决上述问题,我创造了 2 个工作岗位。A-快速执行的工作,B-慢速移动的工作。

我有 2 个石英作业 A 和 B 同时运行,并使用一个标志来决定是运行作业并做一些事情还是运行和退出而不做任何事情。我有一个标志 doStuff ,它的初始值为 0 。当它的值为 1 时,两个工作都应该开始做事,当他们完成时,他们应该将值更新回 0。当值为 0 并且工作开始时,这个工作就不会做这件事了。工作 A 和 B 所做的工作完全相同,但参数不同。理想情况下,两个作业都应该在 flag 为 1 时运行并做一些事情并将值更新为 0。但是当第一个作业运行并在开始第二个作业之前完成时,它会将值更新为 0,当第二个作业运行时它读取值 0 并且不会执行任何操作东西。

doStuff 标志是 DB 列。我可以为工作 B 再添加一列,但这不是一个好的设计,因为我们可能会得到工作 C、工作 D 的要求,而我无法为每个要求添加列。

有没有更好的方法来处理这个问题?

注意:我是 Quartz 框架的新手。

尝试使用新列作为标志,但不是一个好的设计。尝试锁定,但这也不能解决问题。

下面是 InterruptableJob 的执行方法的样子

public void execute(JobExecutionContext jobContext) throws JobExecutionException {
    JobDataMap jobDataMap = jobContext.getMergedJobDataMap();
    final long customerId = jobDataMap.getLong(CUSTOMER_ID_KEY);

    List < QAgentAssetSourceInfo > customerAgents = getValuesBasedOnDoStuff();

    // below code is in Runnable run method and will be started in new thread 
    {
        failedAgents.putAll(agentMgmtHelper.get().doStuff(customerAgents, customer.getId(), null, batchSize));


        // we are done with stuff now make value to 0
        unsetDoStuff();
    });

}

标签: javaconcurrencyquartz-schedulerrace-condition

解决方案


推荐阅读