如何使用spring任务调度处理多个文件时保持一致性?

时间:2018-03-30 08:27:02

标签: java spring multithreading scheduler

我有一个要求,即调度程序将以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文件夹中删除文件。 有没有比文件锁定机制更好的方法来实现这一目标?任何帮助赞赏。

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

一个简单的解决方案是让任务(获取文件并将其分发到多个线程的任务)维护一组已拾取并且当前正在进行的文件。下次它获取文件时,它可以检查此Set并在Set中添加新的文件后仅处理新的文件。问题是,处理文件的线程一旦完成文件就必须从该Set中删除。无论何时操作此Set,都必须使用synchronized块。