File Lock on Write to Disk

I have two independent threads F1 and F2 (more precisely, two instances of java.util.concurrent.FutureTask) that work in parallel.

F1 do some processing and then copy the result to an XML file. He then repeats these steps until he has nothing to do (many XML files are created). F2 looks at the F1 output directory and takes one file, parses it, and does some processing on it.

This works pretty well, except sometimes F2 gets truncated XML data from a file. I mean, incomplete XML where some XML node are missing. The problem is that it does not always play, and files that are truncated are not always the same. Because of this, I think that although F1 writes one file to disk, F2 tries to read the same file. So sometimes I get such an error.

My question is : I wonder if there is any mechanism that blocks (even for reading) the F1 file is currently writing until it completes writing to disk, so F2 will not be able to read it until the file will be unlocked. Or any other way to solve my problem would be happy!

F1 writes the file as follows:

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 reads the file as follows:

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);
}
+3
3

.xml F2, F1 .temp, .xml . , F2 F1, F1 .

+6

java.nio.channels.FileLock API?

(, foo.tmp), (, foo.xml), - ( ) , XML , . , , .

+6

Use the synchronized keyword on a generic object, a File file pointing to a file would be best in this case:

 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
 }
+2
source

Source: https://habr.com/ru/post/1705571/


All Articles