从同一个表读取的两个线程:如何使两个线程不从TASKS表中读取同一组数据

我有一个任务线程在两个单独的tomcat实例中运行。 Task线程在某些where条件下同时读取(使用select)TASKS表,然后进行一些处理。

问题是,有时两个线程都选择相同的任务,因此任务执行两次。 我的问题是如何使两个线程不从TASKS表中读取相同的数据集

我认为您需要一些变量(列),您可以保留上次修改的行日期。 您的线程可以使用相同的修改日期限制读取相同的数据集。

编辑:我没看到“不读”

在这种情况下,您需要另一个表TaskExecutor(taskId,executorId),当某个线程运行任务时,您将数据放入TaskExecutor; 当你启动另一个线程时,它只检查该任务是否已经执行(从RanTask中选择…,其中taskId = …)。 Н还需要处理转换的隔离级别。

这只是因为您的代码(访问数据库)DAOfunction未同步。使其同步,我认为您的问题将得到解决。

如果您提到的TASKS table是数据库表,那么我将使用事务隔离。

作为建议,在trasaction中,如果未设置,则将TASK table的属性设置为某个唯一可识别值。 提交tracaction。 如果一切正常,则线程选择任务。

我没有遇到这个用例,所以请用catuion来对待我的建议。

我认为您需要查看一些信息如何与任何企业作业调度程序一起使用,例如使用Quartz

对于您的用例,有一个更好的工作工具 – 那就是消息。 您持久化需要处理的项目,然后尝试同步工作者之间的访问权限。 在进行此项工作时,您需要解决许多问题 – 通常更新表并从中进行选择不应混合(锁定),因此存储状态不起作用; 既不会在Java代码中同步,因为在服务器重启时也无法生存。

将JMS API与ActiveMQ等消息代理一起使用,可以将消息发布到队列。 此消息将包含要执行的任务的详细信息。 消息代理会将其保留在某处(在其自己的消息存储库或数据库中)。 然后,工作线程将订阅消息代理上的队列,并且每条消息只会传递给其中一个消息。 这是一个非常强大的模型,因为您可以让数百个消息使用者全部执行任务,因此可以很好地扩展。 您还可以根据需要使其具有弹性,因此任务可以在Tomcat和代理重新启动时继续存在。

数据库是否可以提供对此的优雅管理在很大程度上取决于它是使用严格的两阶段锁定(S2PL)还是多版本并发控制(MVCC)技术来管理并发。 在MVCC下,读取不会阻止写入,反之亦然,因此可以使用相对简单的逻辑来管理它。 在S2PL下你会花太多时间来阻止数据库成为管理它的好机制,所以你可能想看一下外部机制。 当然,无论数据库如何,外部机制都可以工作,而MVCC并不是必需的

使用MVCC的数据库是PostgreSQL,Oracle,MS SQL Server(在某些配置中),InnoDB(SERIALIZABLE隔离级别除外),可能还有许多其他数据库。 (这些是我所知的副手。)

我没有在问题中找到关于您使用的数据库产品的任何线索,但如果是PostgreSQL,您可能需要考虑使用咨询锁。 http://www.postgresql.org/docs/current/interactive/explicit-locking.html#ADVISORY-LOCKS我怀疑很多其他产品都有类似的机制。