java - 该进程无法访问该文件,因为它正被另一个进程使用

新手上路,请多包涵

我有一段代码可以监视目录以添加文件。每当将新文件添加到目录时,文件的内容都会被挑选并发布到 kafka 上,然后文件会被删除。

这在我发出单个请求时有效,但一旦我将我的代码提交给来自 jMeter 的 5 或 10 个用户请求,内容就会成功发布在 kafka 上,但代码无法删除文件。我收到一条消息 FileSystemException The process cannot access the file because it is being used by another process.

我想有一些我看不到的并发问题。

 public void monitor() throws IOException, InterruptedException {
    Path faxFolder = Paths.get(TEMP_FILE_LOCATION);
    WatchService watchService = FileSystems.getDefault().newWatchService();
    faxFolder.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
    boolean valid = true;
    do {
        WatchKey watchKey = watchService.take();
        for (WatchEvent<?> event : watchKey.pollEvents()) {
            if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
                String fileName = event.context().toString();
                publishToKafka(new File(TEMP_FILE_LOCATION + fileName).toPath(), "topic");
            }
        }
        valid = watchKey.reset();
    } while (valid);
}

private void publishToKafka(Path path, String topic) {
    try (BufferedReader reader = Files.newBufferedReader(path)) {
        String input = null;
        while ((input = reader.readLine()) != null) {
            kafkaProducer.publishMessageOnTopic(input, topic);
        }
    } catch (IOException e) {
        LOG.error("Could not read buffered file to send message on kafka.", e);
    } finally {
        try {
            Files.deleteIfExists(path); // This is where I get the exception
        } catch (IOException e) {
            LOG.error("Problem in deleting the buffered file {}.", path.getFileName(), e);
        }
    }
}

异常日志:

 java.nio.file.FileSystemException: D:\upload\notif-1479974962595.csv: The process cannot access the file because it is being used by another process.

    at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
    at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
    at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
    at sun.nio.fs.WindowsFileSystemProvider.implDelete(Unknown Source)
    at sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(Unknown Source)
    at java.nio.file.Files.deleteIfExists(Unknown Source)
    at com.panasonic.mdw.core.utils.MonitorDirectory$FileContentPublisher.publishToKafka(MonitorDirectory.java:193)
    at com.panasonic.mdw.core.utils.MonitorDirectory$FileContentPublisher.sendData(MonitorDirectory.java:125)
    at com.panasonic.mdw.core.utils.MonitorDirectory$FileContentPublisher.run(MonitorDirectory.java:113)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

原文由 sensitive_piece_of_horseflesh 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 988
1 个回答

查看您的代码,似乎当线程选择一个文件再次发布时,另一个线程正在选择它进行发布。这就是为什么没有人能够删除它。它必须只是并发问题。您应该根据标准重新设计代码:可以同时运行的步骤和不能同时运行的步骤。所以整个过程中的步骤是:

  1. 拿起一个文件(主线程应该这样做)
  2. 发布一个文件(调用其他线程来做)
  3. 删除文件(调用线程应该删除它)
  4. 检查是否存在任何文件(再次主线程可以做到)

同样,在选择文件的那一刻,您可以将其读入 buffer ,将其删除,然后继续发布。这将确保主线程不会将此文件分配给其他线程。

原文由 Goro 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题