gpt4 book ai didi

java - Java中的多线程访问文件

转载 作者:行者123 更新时间:2023-12-01 17:46:30 25 4
gpt4 key购买 nike

我正在使用 Java 开发多线程服务器。服务器监视文件目录。客户端可以询问服务器:

  • 从服务器目录下载文件
  • 将现有文件的新版本上传到服务器,覆盖服务器目录中的旧版本。

为了进行传输,我计划使用 FileChannels 和 SocketChannels,并使用方法transferFrom和transferTo。根据文档,这两个方法都是线程安全的。问题是对这两个函数的一次调用不足以完全读取/写入文件。

如果同一文件同时有多个请求,就会出现问题。在这种情况下,多个线程可以对同一文件执行读/写操作。现在,根据 Java 文档,对 TransferFrom/transferTo 的单个调用是线程安全的。但是对这两个函数的一次调用不足以完全读取/写入文件。如果线程 A 正在回复下载请求,而线程 B 正在回复引用同一文件的上传请求,则可能会发生以下情况:

  1. 线程 A 开始读取文件
  2. 在线程 A 中,由于某种原因,读取调用在 EOF 之前返回
  3. 线程 B 通过一次写入调用覆盖整个文件
  4. 线程 A 继续从文件中读取

在这种情况下,下载客户端会收到旧版本的一部分和新版本的一部分。

<小时/>

为了解决这个问题,我认为我应该使用某种锁定,但我不确定如何以有效的方式做到这一点。我可以创建两个同步方法来读取和写入,但这显然会造成太多争用。

我想到的最佳解决方案是使用锁 strip 化。在执行任何读/写操作之前,会计算基于文件名的哈希值。然后,获取位置lockArr[hash % numOfLocks]的锁。我还认为我应该使用 ReadWriteLocks,因为应该允许多个同时读取。

现在,这是我对问题的分析,我可能完全错误。有没有更好的解决办法?

最佳答案

锁定意味着某人必须等待其他人 - 这不是最好的解决方案。

当客户端上传文件时,您应该将其写到同一磁盘上(通常在同一目录中)的临时文件中,然后当文件上传完成时:

  1. 将旧版本重命名为临时名称。任何当前的读者都应该被迫关闭旧版本,重新打开临时版本,并寻找正确的位置。
  2. 将上传的文件重命名为目标文件名。
  3. 当任何读者使用完旧文件的临时版本后,将其删除。

在典型的实现中,您需要一个集中式类(我们称之为ConcurrentFileAccessor)来管理线程之间的交互。

读者需要向此类注册,并在实际读取操作期间同步某些对象。当上传完成时,编写者必须声明所有这些锁以阻止读取,关闭所有读取的文件,重命名旧版本,重新打开,查找,然后释放它们以允许读取器继续。

关于java - Java中的多线程访问文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54573948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com