我有两个独立的线程F1和F2(准确地,java.util.concurrent.FutureTask中的两个实例),该并行运行。

F1做一些处理,并随后在XML文件中的结果复制。然后,重复这些步骤,直到它无关(创建许多XML文件)。 F2看在F1输出目录,并采取一个文件,分析它,并在其上执行一些处理。

这工作得很好,除了从文件中,有时,F2被截断的XML数据。我的意思是说一个不完整的XML,一些XML节点不存在。问题是,它并不总是reproductible,而被截断的文件并不总是相同的。 正因为如此,我想,虽然F1在磁盘上写入一个文件,F2是试图读取相同的文件。这就是为什么有时我得到这样的错误的。

我的提问:我想知道是否有一些机制,锁(甚至读)的文件F1目前正在写,直到它已经完全结束将它写在磁盘上,因此F2不会能够阅读它,直到该文件被解锁。或任何其他方式来解决我的问题将受到欢迎!

F1被写入文件是这样的:

try {
    file = new File("some-file.xml");
    FileUtils.writeStringToFile(file, xmlDataAsString);
} catch (IOException ioe) {
    LOGGER.error("Error occurred while storing the XML in a file.", ioe);
}

F2被读取文件是这样的:

private File getNextFileToMap() {
    File path = getPath(); // Returns the directory where F1 stores the results...
    File[] files = path.listFiles(new FilenameFilter() {
        public boolean accept(File file, String name) {
            return name.toLowerCase().endsWith(".xml");
        }
    });
    if (files.length > 0) {
        return files[0];
    }
    return null;
}

// Somewhere in my main method of F2
...
f = getNextFileToMap();
Node xmlNode = null;
try {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse(f);
    if (doc != null) {
        xmlNode = doc.getDocumentElement();
    }
} catch (Exception e) {
    LOGGER.error("Error while getting the XML from the file " + f.getAbsolutePath(), e);
}
有帮助吗?

解决方案

既然你已经在F2 .xml文件过滤,有F1输出到.temp文件,然后重命名为.xml作为最后一步。这样一来,F2将忽略该文件F1正在直到F1是完全用它做。

其他提示

使用关键字同步在一个共同的对象,文件对象指向文件将是最好在这种情况下:

 class MyFileFactory {
     private static HashMap<string,File> files = new HashMap<String,File>();
     public static File get(String name) {
         if (!files.keyExists(name)) {
              files.put(name, new File(name));
         }
         return files.get(name);
     }
 }

 // Another class
 synchronized(File f = MyFileFactory::get("some-file.xml")) {
      // read or write here
 }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top