【问题标题】:How to maintain consistency while processing multiple files using spring task scheduling?使用spring任务调度处理多个文件时如何保持一致性?
【发布时间】:2018-04-09 14:00:19
【问题描述】:

我有一个要求,调度程序将在 2 分钟的固定延迟内触发任务。 任务从目录中挑选所有文件(例如 abc)并将它们分发到多个线程进行处理。 每个线程执行以下操作, 1. 从特定文件(例如 file1.csv)中读取数据。 2. 在验证后追加一些数据,并将结果数据写入更新(例如 xyz)目录中的另一个文件(例如 file1-updated.csv)。 3.从目录abc中删除输入文件file1.csv。

当最终用户执行某些操作时,文件将从其他服务器动态推送到 abc 目录。当调度程序每 2 分钟触发一次时,它会拾取所有文件并将它们分发到线程,正如我上面解释的那样。 现在的问题是 - 假设有 2 个文件 file1.csv 和 file2.csv 并且调度程序选择它们并在第一个触发器中分发到线程。现在 file3.csv 已被推送到 abc 目录,并在 2 分钟后再次触发调度程序。现在,调度程序应该只将 file3.csv 分配给线程而不是 file1.csv 和 file2.csv,因为它们已经在之前的触发器中被拾取并且正在处理中。我必须确保只有新文件才会分发给线程进行处理。

我可以使用文件锁定机制吗? 1.一旦文件被赋予线程,就锁定文件(使用java文件锁定机制)。 2. 当调度器第二次触发并将文件分发到线程时,检查文件是否处于锁定状态,如果没有则仅进一步处理,否则刚刚从线程中出来。 3. 文件处理完成后,解除锁定并从 abc 文件夹中删除文件。 有没有比文件锁定机制更好的方法来实现这一点?任何帮助表示赞赏。

【问题讨论】:

  • 两个线程同时处理两个文件比一个线程顺序处理两个文件更快的基本假设可能是错误的。您需要先对此进行调查。

标签: java spring multithreading scheduler


【解决方案1】:

一个简单的解决方案是让任务(拾取文件并将它们分发到多个线程的任务)维护一组它已拾取且当前正在进行的所有文件。下次它拾取文件时,它可以签入这个 Set 并在将新文件添加到 Set 后只处理新文件。问题是,处理文件的线程在处理完文件后必须从该 Set 中删除。每当您操作此 Set 时,您都必须使用同步块。

【讨论】:

  • 谢谢阿穆丹!解决方案看起来不错。但我也想检查我是否可以通过文件锁定机制来实现这一点。我已经更新了这个问题。请让我知道你的想法。
  • @bharath,我对 FileLock 了解不多,但是 javadoc 说“文件锁代表整个 Java 虚拟机持有。它们不适合控制对文件的访问通过同一虚拟机中的多个线程”。您可以在这个问题中看到建议使用 FileLock,因为用例不同,两个不同的 JVM 想要专门对文件进行操作。 stackoverflow.com/questions/128038/… 所以,我认为 FileLock 不是适合您的场景的解决方案。
【解决方案2】:

您可以在选择文件时重命名文件(例如添加后缀 .lock)以将文件标记为“进行中”。

下次执行任务时,会过滤掉那些被标记的文件。

现在,如果两个任务同时标记文件(假设固定延迟非常短),您可能会遇到并发问题。在这种情况下,您应该使用线程安全组件来标记正在进行的文件。

【讨论】:

    猜你喜欢
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多