java - 无法在 Windows 上中断 Java 中的命名管道 channel

标签 java nio named-pipes

我在 Windows 上命名了管道 .\pipe\pipe1,我想使用 Java 进行读取。

根据文档,FileChannel 应该是可中断的。如果读取线程被另一个线程中断,则读取应抛出 ClosedByInterruptException。这可能适用于常规文件,但我现在有一个命名管道。

我的情况是这样的:

RandomAccessFile raf = new RandomAccessFile("\\\\.\\pipe\\pipe1", "r");
FileChannel fileChannel = raf.getChannel();

// later in another thread "readThread"
fileChannel.read(buffer);

// outside the thread reading
readThread.interrupt();

问题在于,对interrupt的调用将被阻塞,而read将保持阻塞状态,直到向命名管道写入某些内容,以便read将停止阻塞。

当管道尚未关闭时没有任何内容写入管道时,我需要能够中止/取消读取。

为什么用 NIO 类进行中断不起作用?有没有一种解决方案可以解决这个问题,并且不涉及忙等待或 sleep 状态ready?此问题的最佳解决方案是什么或有解决方法吗?

最佳答案

我还没有找到如何取消读取问题的真正解决方案。但无论如何我都需要调整,现在将解释原因。如果您对阻止阅读的原始问题有任何补充,您可以发布额外的答案。

命名管道可以像文件一样对待,并单独打开以使用经典的 Java IO 流进行读写。然而,命名管道通常像套接字一样使用,因此它需要打开一个文件。所以我可以像这样使用 Java IO 流:

RandomAccessFile raf = new RandomAccessFile("\\\\.\\pipe\\pipe1", "rws");
FileChannel fileChannel = raf.getChannel();
InputStream fis = Channels.newInputStream(fileChannel);
OutputStream fos = Channels.newOutputStream(fileChannel);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
PrintWriter pw = new PrintWriter(fos, true);

现在人们稍后会注意到的一个问题是:如果你边读边写,事情就会陷入困境。看来并发读/写是不可能的,这是大纲here .

为了解决这个问题,我使用了一个 ReentrantLock 设置为 fair 来从读/写切换。读取线程正在检查准备情况,如果完成写入并期望在此之后得到响应,则可以通过中断触发读取线程。如果准备就绪,读取缓冲区将被清空。如果尚未准备好,则可以为偶发的预期消息安排或模拟一个时间间隔。最后一部分不是最佳的,但实际上非常适合我的用例。

这样,我们就可以构建一种解决方案,在该解决方案中,所有线程都可以编排以正确终止,而不会阻塞且开销最小。

关于java - 无法在 Windows 上中断 Java 中的命名管道 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44182265/

相关文章:

java - JMenuItem 设置对齐方式和最大尺寸

java - 如何为Spring Integration提供转换器?

java.nio.file.FileAlreadyExistsException 如何在 java7 中解决这个问题

java - 关于 Files.notExists 的 SonarLint 规则

Java nio 监视服务 : Watch Windows drives list

java - 为什么这个编译得很好(明显的运行时异常如下)

java - 如何使用增强的 for 循环打印数组

multithreading - bash:写入命名管道是原子的吗?

c# - 如何确保只有我的程序可以访问命名管道?

windows - 创建进程退出时 Windows 中的命名管道会发生什么情况?