无法中断 Windows 上的 Java 中的命名管道通道



我已经在Windows上命名了管道.pipepipe1,我想用Java从中读取。

从文档中看,FileChannel应该是可中断的。如果读取线程从另一个 therad 中断,读取应抛出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将保持阻塞状态,直到写入命名管道的某些内容,以便读取将停止阻塞。

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

为什么打断NIO课程不起作用?有没有不涉及忙碌等待或与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);

现在人们以后会注意到的一个问题是:如果你边读边写,事情就会变得挂断。似乎无法同时读取/写入,这在这里概述。

为了解决这个问题,我使用了一个公平的ReentrantLock来切换阅读/写作。读取线程正在检查就绪性,如果完成写入并期望在此之后得到响应,则可以通过中断触发。如果准备就绪,则排空读数缓冲液。如果尚未准备就绪,则可以为偶尔预期的消息计划或模拟间隔。最后一部分不是最佳的,但实际上对于我的用例来说效果很好。

有了这个,可以构建一个解决方案,其中可以协调所有线程以正确终止,没有阻塞和最小的开销。

最新更新