2017-04-06 4 views
0

verschieben Ich habe Multithread-Anwendung. Meine App hat einen Spring-Scheduler, der mehrere Threads startet, die Dateien von einem bestimmten Ort aus bearbeiten. Ich erhalte Datei, um zu verarbeiten, indem ich Files.newDirectoryStream(taskFolder, filter) aufruft und über Ergebnis iteriere. Ich muss sicherstellen, dass nur ein Thread Dateien zur Verarbeitung übernimmt. Ich versuche, Datei mit ATOMIC_MOVE umzubenennen, um zu markieren, dass es von einem Thread verarbeitet wird. Ich erwarte, dass andere Threads diese Datei nicht umbenennen können (MoveFileException sollte ausgelöst werden), was dazu führt, dass die Datei nicht von diesen Threads verarbeitet wird (die Logik im catch-Block von MoveFileException beendet den Prozess).Mehrere Threads können die gleiche Datei mit ATOMIC_MOVE unter Windows

try { 
    Files.move(source, target, StandardCopyOption.ATOMIC_MOVE); 
} catch (IOException e) { 
    throw new MoveFileException("An error occurred while moving the file from: " + source.toString() + " to: " + target.toString(), e); 
} 

Aber es funktioniert nicht. Immer noch 2 oder mehr Threads können meine Datei ohne Ausnahme umbenennen. Also wie kann ich sicherstellen, dass Datei nur von einem Thread genommen wird.

EDIT

Ich liefere mehr Code zu verstehen, was ich tun möchte.

Import.java

for (Path path : filesToProcessPath) { 
    final FileToProcessRepresentation fileToProcessRepresentation = new FileToProcessRepresentation(path.toString()); 

    try { 
     fileRepository.moveFileToPendingState(fileToProcessRepresentation); 
    } catch (MoveFileException e) { 
     LOGGER.debug("File [" + fileToProcessRepresentation.getUri() + "] could be process by another thread", e); 
     continue; 
    } catch (Exception e) { 
     LOGGER.error(e.getMessage(), e); 
     continue; 
    } 

    //logic 

} 

FileRespository.java

public void moveFileToPendingState(final FileToProcessRepresentation fileToMove) throws MoveFileException { 
    moveFiles(fileToMove, fileToMove.getPendingUri()); 
    fileToMove.toPending(); 
} 

private void moveFiles(final FileToProcessRepresentation s, final String uri) throws MoveFileException { 
    Path sourceFile = Paths.get(s.getUri()); 
    Path destinationFile = Paths.get(uri); 
    moveFiles(sourceFile, destinationFile); 
} 

private void moveFiles(final Path source, final Path target) throws MoveFileException { 
    try { 
     Files.move(source, target, StandardCopyOption.ATOMIC_MOVE); 
    } catch (IOException e) { 
     throw new MoveFileException("An error occurred while moving the file from: " + source.toString() + " to: " + target.toString(), e); 
    } 
} 
+0

Wenn es Ihnen möglich ist, stattdessen mit 'FileChannel' zu arbeiten und dessen' lock() 'Funktionalität zu benutzen? –

+0

@ M.Prokhorov ja. Ich kann den Ansatz komplett ändern. Was ich brauche ist, dass es funktioniert. –

+0

* Aber es funktioniert nicht * Das ist keine nützliche Beschreibung. *Was geschieht? –

Antwort

0

ich beschlossen endlich mein Problem synchronized zu moveFileToPendingState Methode fügen Sie einfach.

Verwandte Themen