2

我必须进行批处理以自动化业务流程。我必须定期轮询目录以检测新文件并进行处理。在处理旧文件的同时,新文件可以进来。目前,我使用石英调度器和线程同步来确保只有一个线程可以处理文件。

部分代码如下:

应用程序上下文.xml

<bean id="methodInvokingJob"
  class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><br/>
  <property name="targetObject" ref="documentProcessor" /><br/>
  <property name="targetMethod" value="processDocuments" /><br/>
</bean>

文档
处理器.....

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;
        }
     }
  }
}

对于当前代码,当一个线程正在处理时,我必须阻止其他线程处理文件。这是一个好主意吗 ?或者我们支持多线程处理。在这种情况下,我如何知道哪些文件正在处理以及哪些文件刚刚到达?任何想法都非常感谢。

4

2 回答 2

5

我会用这些部分构建它:

  1. 与 TxF 的城堡交易

  2. FileSystemWatcher Java 版本

  3. TransactionScope(没有 java 版本,除非你经常破解它)

  4. 无锁队列*(讨论 perf Java 与 .Net 的论文,也许可以从它们那里获取 Java的源代码)基于 Java 锁的队列

    这样:

当有一个新文件时,文件系统观察程序会检测到它(记住放置正确的标志,处理错误条件并设置 Enbled <- True 并注意双精度),将文件路径放入队列中。

您有一个应用程序线程,n 个工作线程。如果这是唯一的应用程序,它们会在队列中旋转等待 TryDequeue,否则它们会在监视器上阻塞 while(!Monitor.Enter(has_items)) ;

当工作线程通过出队操作获得路径时,它开始处理它,现在没有其他线程可以处理它。如果有双倍输出(取决于您的设置),那么您可以在编写输出文件时使用文件事务。如果 Commit 操作失败,那么您知道另一个线程已经写入了输出文件,并继续轮询队列。

于 2010-03-08T10:28:21.577 回答
2

我会做以下事情:

  • 一个线程获取您的文件名并将它们添加到同步队列中。

  • 多个线程进行实际读取:从同步队列中获取一个项目并处理它。

要检查文件是否被使用,您可以简单地尝试重命名/移动它。

于 2010-03-08T10:17:20.233 回答