线程中断未结束输入流读取上的阻塞调用
我正在使用 RXTX 从串行端口读取数据。读取是在按以下方式生成的线程中完成的:
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(port);
CommPort comm = portIdentifier.open("Whatever", 2000);
SerialPort serial = (SerialPort)comm;
...settings
Thread t = new Thread(new SerialReader(serial.getInputStream()));
t.start();
SerialReader 类实现 Runnable 并无限循环,从端口读取数据并将数据构建到有用的包中,然后将其发送到其他应用程序。但是,我将其简化为以下简单内容:
public void run() {
ReadableByteChannel byteChan = Channels.newChannel(in); //in = InputStream passed to SerialReader
ByteBuffer buffer = ByteBuffer.allocate(100);
while (true) {
try {
byteChan.read(buffer);
} catch (Exception e) {
System.out.println(e);
}
}
}
当用户单击停止按钮时,会触发以下功能,理论上应该关闭输入流并摆脱阻塞的 byteChan.read(buffer) 调用。代码如下:
public void stop() {
t.interrupt();
serial.close();
}
但是,当我运行此代码时,我从未收到 ClosedByInterruptException,一旦输入流关闭,它应该触发。此外,执行会阻塞对serial.close()的调用——因为底层输入流仍然阻塞在读取调用上。我尝试用 byteChan.close() 替换中断调用,这应该会导致 AsynchronousCloseException,但是,我得到了相同的结果。
对我所缺少的任何帮助将不胜感激。
I'm using RXTX to read data from a serial port. The reading is done within a thread spawned in the following manner:
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(port);
CommPort comm = portIdentifier.open("Whatever", 2000);
SerialPort serial = (SerialPort)comm;
...settings
Thread t = new Thread(new SerialReader(serial.getInputStream()));
t.start();
The SerialReader class implements Runnable and just loops indefinitely, reading from the port and constructing the data into useful packages before sending it off to other applications. However, I've reduced it down to the following simplicity:
public void run() {
ReadableByteChannel byteChan = Channels.newChannel(in); //in = InputStream passed to SerialReader
ByteBuffer buffer = ByteBuffer.allocate(100);
while (true) {
try {
byteChan.read(buffer);
} catch (Exception e) {
System.out.println(e);
}
}
}
When a user clicks a stop button, the following functionality fires that should in theory close the input stream and break out of the blocking byteChan.read(buffer) call. The code is as follows:
public void stop() {
t.interrupt();
serial.close();
}
However, when I run this code, I never get a ClosedByInterruptException, which SHOULD fire once the input stream closes. Furthermore, the execution blocks on the call to serial.close() -- because the underlying input stream is still blocking on the read call. I've tried replacing the interrupt call with byteChan.close(), which should then cause an AsynchronousCloseException, however, I'm getting the same results.
Any help on what I'm missing would be greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您无法仅通过包装将不支持可中断 I/O 的流放入
InterruptibleChannel
中(而且,ReadableByteChannel
不会扩展中断通道
)。您必须查看底层
InputStream
的约定。SerialPort.getInputStream()
关于其结果的可中断性有何说明?如果它什么也没说,你应该假设它忽略了中断。对于任何不明确支持可中断性的 I/O,唯一的选择通常是从另一个线程关闭流。这可能会在调用流时阻塞的线程中立即引发
IOException
(尽管它可能不是AsynchronousCloseException
)。然而,即使这也极大地依赖于 InputStream 的实现,而且底层操作系统也可能是一个因素。
请注意
newChannel()
返回的ReadableByteChannelImpl
类的源代码注释:You can't make a stream that doesn't support interruptible I/O into an
InterruptibleChannel
simply by wrapping it (and, anyway,ReadableByteChannel
doesn't extendInterruptibleChannel
).You have to look at the contract of the underlying
InputStream
. What doesSerialPort.getInputStream()
say about the interruptibility of its result? If it doesn't say anything, you should assume that it ignores interrupts.For any I/O that doesn't explicitly support interruptibility, the only option is generally closing the stream from another thread. This may immediately raise an
IOException
(though it might not be anAsynchronousCloseException
) in the thread blocked on a call to the stream.However, even this is extremely dependent on the implementation of the
InputStream
—and the underlying OS can be a factor too.Note the source code comment on the
ReadableByteChannelImpl
class returned bynewChannel()
:RXTX SerialInputStream(serial.getInputStream() 调用返回的内容)支持超时方案,最终解决了我的所有问题。在创建新的 SerialReader 对象之前添加以下内容会导致读取不再无限期地阻塞:
在 SerialReader 对象中,我必须更改一些内容才能直接从 InputStream 读取而不是创建 ReadableByteChannel,但现在,我可以停止并重新启动阅读器没有问题。
The RXTX SerialInputStream (what is returned by the serial.getInputStream() call) supports a timeout scheme that ended up solving all my problems. Adding the following before creating the new SerialReader object causes the reads to no longer block indefinitely:
Within the SerialReader object, I had to change a few things around to read directly from the InputStream instead of creating the ReadableByteChannel, but now, I can stop and restart the reader without issue.
我正在使用下面的代码来关闭 rxtx。我运行了启动和关闭它们的测试,似乎工作正常。我的读者看起来像:
谢谢
i am using the code below to shutdown rxtx. i run tests that start them up and shut them down and the seems to work ok. my reader looks like:
thanks