当前位置: 首页 > 面试题库 >

如何在Java Servlet中同步文件访问?

壤驷高洁
2023-03-14
问题内容

我创建了一个小型Java servlet,其目的很简单:调用它后,它将执行以下步骤:

  1. 从本地文件系统读取文件foo.json
  2. 处理文件中的数据并对其进行一些更改
  3. 将更改写回文件

代码的简化版:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    FileInputStream inputStream = new FileInputStream("foo.json");
    String filecontent = IOUtils.toString(inputStream);
    inputStream.close();

    JSONObject json = new JSONObject(filecontent);

    doSomeChangesTo(json);

    FileWriter writer = new FileWriter("foo.json");
    writer.write(json.toJSONString());
    writer.flush();
    writer.close();
}

现在,我面临一个问题,即可能有两个或多个对servlet的http请求几乎同时调用servlet。为了避免对同一文件进行多次并行写访问,我需要以某种方式进行同步。根据我对servlet生命周期过程的了解,每个请求都会产生一个新线程,因此使用FileLock可能不会产生任何影响:

文件锁代表整个Java虚拟机保留。它们不适用于控制同一虚拟机中的多个线程对文件的访问。

(来自http://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileLock.html)

我想使用synchronized(){}关键字也将不起作用,因为我想同步文件系统访问而不是变量/对象访问。

因此,当在该servlet上发生多个并行请求时,如何同步servlet中的文件系统访问?


问题答案:

我想使用synchronized(){}关键字也将不起作用,因为我想同步文件系统访问而不是变量/对象访问。

使用synchronized可以工作。您假设如果要控制从多个线程对对象 X的 访问,则必须synchronized在该对象上使用。你不知道
您可以synchronized任何 对象上使用,前提是所有访问都使用同一对象。

实际上,通常 最好 使用单独的private锁对象进行同步,因为这样一来,类外的代码就无法在锁上进行同步。

因此,您可能会有类似的情况,每个共享文件都有一个实例:

 public class SharedFile
 {
      private final File path;
      private final Object lock = new Object();

      public SharedFile(File path) {
         this.path = path;
      }

      public void process(.....) throws IOException {
         synchronized(lock) {
            try(InputStream = new FileInputStream(path)) {
               ....
            }
         }
      }
 }


 类似资料:
  • 我试图了解正确的方法来同步文件读/写在PHP中使用群。 我有两个php脚本。 testread.php: 和testwrite。php: 现在我跑testread.php,让它挂在那里。然后我在另一个会话中运行testwrite.php。正如预期的那样,flock在testwrite.php.失败但是,当testwrite.php退出时,文件test.txt的内容被清除。事实是,即使文件在另一个进

  • 我正在尝试做一个应用程序,与音频文件工作。我必须在应用程序的一部分中导入和合并来自Firebase的音频文件。 下面是来自合并操作的代码块; 问题是下载firebase文件的代码继续工作。正如您所看到的,我试图用无限循环来修复这一点,但Firebase在没有正确加载时创建文件,因此解决方案没有成功。 我试图编写为加入onSuccess事件而创建的数组,但在这种情况下,我将无法完全准备好要使用的数组

  • 我想读取一个文件,并使用FileReader对象将其转换为base64编码的字符串。以下是我使用的代码: 但是在这种情况下,我在事件处理程序(onLoadend事件)中得到转换的结果。我想要一个同步方法。有没有办法"readAsDataURL"方法可以直接返回'result_base64'变量的值?

  • 但我进的是空异常。有什么问题,有人能帮忙吗?