我必须进行批处理以自动化业务流程。我必须定期轮询目录以检测新文件并进行处理。在处理旧文件时,可以使用新文件。目前,我使用quartz调度程序和线程同步来确保只有一个线程可以处理文件。
部分代码是:
应用程序的context.xml
<bean id="methodInvokingJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><br/>
<property name="targetObject" ref="documentProcessor" /><br/>
<property name="targetMethod" value="processDocuments" /><br/>
</bean>
DocumentProcessor
.....
public void processDocuments() {
LOG.info(Thread.currentThread().getName() + " attempt to run.");
if (!processing) {
synchronized (this) {
try {
processing = true;
LOG.info(Thread.currentThread().getName() + " is processing");
List<String> xmlDocuments = documentManager.getFileNamesFromFolder(incomingFolderPath);
// loop over the files and processed unlock files.
for (String xmlDocument : xmlDocuments) {
processDocument(xmlDocument);
}
}
finally {
processing = false;
}
}
}
}
对于当前代码,我必须阻止其他线程在处理一个线程时处理文件。这是一个好主意吗 ?或者我们支持多线程处理。在这种情况下,我如何知道哪些文件正在处理以及哪些文件刚刚到达?任何想法都非常感激。
答案 0 :(得分:5)
我会用这些部分构建它:
A lock-free queue *(论文讨论了针对性能的Java与.Net,或许可以获得来源from them for Java)Java lock-based queues
这样:
当有新文件时,文件系统观察程序检测到它(记住放置正确的标志,处理错误条件并设置Enbled&lt; - True并注意双打),将文件路径放入队列中。 / p>
你有一个应用程序线程,n个工作线程。如果这是唯一的应用程序,他们会在队列上旋转等待TryDequeue,否则它们会在监视器上阻塞(!Monitor.Enter(has_items));
当一个工作线程通过de-queue操作获得一个路径时,它开始处理它,现在没有其他线程可以对它进行操作。如果有两倍的输出(取决于您的设置),则可以在编写输出文件时使用文件事务。如果Commit操作失败,那么您知道另一个线程已经写入了输出文件,并继续轮询队列。
答案 1 :(得分:2)
我会做以下事情:
获取文件名并将其添加到同步队列的一个线程。
执行实际阅读的多个线程:从同步队列中获取一个项目并进行处理。
要检查文件是否被使用,您只需尝试重命名/移动它即可。