【问题标题】:Why does InputStream read method block the resource?为什么 InputStream 读取方法会阻塞资源?
【发布时间】:2019-03-01 01:11:34
【问题描述】:

为什么 InputStream 的 read 方法在没有内容可读取的情况下阻塞资源?

假设我有一个以 RW 模式打开的 RandomAccessFile,我使用文件描述符创建 InputStream / OutputStream。

线程 1 正在尝试从文件中读取,但没有可用的内容。 此时,如果线程 2 尝试写入文件,则会被阻塞。

为什么会这样?

【问题讨论】:

  • 你为什么不自己试试看呢?这就是所谓的研究,是开发人员学习的绝佳工具。
  • 我做到了。线程被阻塞。我试图理解为什么它会阻止整个资源?
  • 如果你已经知道它会阻塞,为什么还要问 if 它会阻塞呢?如果你想问为什么,为什么你的问题是问“会被屏蔽吗?”,而不是“为什么会被屏蔽?”??
  • 已更新。我的错。如果你知道,请帮助我理解。
  • 真正的问题是,为什么要从文件描述符创建 InputStream / OutputStream,而不是独立创建它们。

标签: java multithreading randomaccessfile


【解决方案1】:

FileDescriptor是携带OS文件句柄的对象,也就是携带文件指针的对象。

一次只有一个线程可以使用文件句柄/文件指针,因为FileDescriptor 不支持多线程。访问已同步。

如果你想让两个线程独立访问文件,那么你需要两个 FileDescriptor。

为了证明我的共享文件指针的观点,如果您交替读取FileInputStream 并写入FileOutputStream,您认为会发生什么?

这里是显示发生了什么的代码:

String fileName = "Test.txt";
Files.writeString(Paths.get(fileName), "abcdefghijklmnopqrstuvwxyz", StandardCharsets.US_ASCII);

try (RandomAccessFile raFile = new RandomAccessFile(fileName, "rw");
     FileInputStream in = new FileInputStream(raFile.getFD());
     FileOutputStream out = new FileOutputStream(raFile.getFD()) ) {

    byte[] buf = new byte[4];
    for (int i = 0; i < 3; i++) {
        int len = in.read(buf);
        System.out.println(new String(buf, 0, len, StandardCharsets.US_ASCII));

        out.write("1234".getBytes(StandardCharsets.US_ASCII));
    }
}

String s = Files.readString(Paths.get(fileName), StandardCharsets.US_ASCII);
System.out.println(s);

输出

abcd
ijkl
qrst
abcd1234ijkl1234qrst1234yz

如您所见,读取 4 个字节返回字节 0-3 并移动文件指针,因此写入 4 个字节替换字节 4-7,然后读取 4 个字节返回字节 8-11,写入 4 个字节替换字节12-15,依此类推。

【讨论】:

  • 这是有道理的。谢谢@Andreas。
猜你喜欢
  • 1970-01-01
  • 2010-10-11
  • 2013-01-05
  • 1970-01-01
  • 2021-11-27
  • 2010-11-28
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
相关资源
最近更新 更多