【问题标题】:Multiple threads invoking apache commons io FileUtils.contentEquals() static method in parallel多个线程并行调用 apache commons io FileUtils.contentEquals() 静态方法
【发布时间】:2014-09-14 07:06:33
【问题描述】:

如果多个线程并行调用apachecommons ioFileUtils.contentEquals()静态方法会发生什么?

由于这个方法只包含局部变量,我们可以保证每次执行的最终结果没有任何竞争条件吗?

请就此提出建议。

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    这取决于您的多个线程传递相同的参数还是不同的参数。具有不同参数的多个线程应该是线程安全的,因为没有资源争用。

    如果您通过多个线程传递相同的参数,我首先会质疑是否需要这样做。但是忽略这一点,应该没问题,因为该方法创建了独立的输入流。在这种情况下,唯一可能出错的是操作系统抱怨多次访问同一文件。

    【讨论】:

      【解决方案2】:

      此方法调用 IOUtils.contentEquals,我认为,在多线程环境中没有什么可以制造竞争条件。

      FileUtils.contentEquals()

      public static boolean contentEquals(File file1, File file2) throws IOException {
          boolean file1Exists = file1.exists();
          if (file1Exists != file2.exists()) {
              return false;
          }
      
          if (!file1Exists) {
              // two not existing files are equal
              return true;
          }
      
          if (file1.isDirectory() || file2.isDirectory()) {
              // don't want to compare directory contents
              throw new IOException("Can't compare directories, only files");
          }
      
          if (file1.length() != file2.length()) {
              // lengths differ, cannot be equal
              return false;
          }
      
          if (file1.getCanonicalFile().equals(file2.getCanonicalFile())) {
              // same file
              return true;
          }
      
          InputStream input1 = null;
          InputStream input2 = null;
          try {
              input1 = new FileInputStream(file1);
              input2 = new FileInputStream(file2);
              return IOUtils.contentEquals(input1, input2);
      
          } finally {
              IOUtils.closeQuietly(input1);
              IOUtils.closeQuietly(input2);
          }
      }
      

      IOUtils.contentEquals()

      public static boolean contentEquals(InputStream input1, InputStream input2)
              throws IOException {
          if (!(input1 instanceof BufferedInputStream)) {
              input1 = new BufferedInputStream(input1);
          }
          if (!(input2 instanceof BufferedInputStream)) {
              input2 = new BufferedInputStream(input2);
          }
      
          int ch = input1.read();
          while (EOF != ch) {
              int ch2 = input2.read();
              if (ch != ch2) {
                  return false;
              }
              ch = input1.read();
          }
      
          int ch2 = input2.read();
          return ch2 == EOF;
      }
      

      【讨论】:

        【解决方案3】:

        通过查看 FileUtils.contentEquals 的源代码,它使用 BufferedInputStream 来比较两个文件(通过将两个文件的 InputStream 提供给 IOUtils.contentEquals)。

        而且由于 BufferedInputStream 应该是线程安全的(至少我读过它,我自己从未尝试过),我认为 FileUtils.contentEquals 也应该是线程安全的。

        【讨论】:

          猜你喜欢
          • 2022-10-19
          • 2011-09-06
          • 2018-09-06
          • 1970-01-01
          • 2023-04-09
          • 2011-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多