JDS*_*JDS 10 java multithreading channel rxtx nonblocking
我正在使用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();
Run Code Online (Sandbox Code Playgroud)
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
当用户单击停止按钮时,将触发以下功能,理论上应关闭输入流并中断阻塞byteChan.read(缓冲区)调用.代码如下:
public void stop() {
t.interrupt();
serial.close();
}
Run Code Online (Sandbox Code Playgroud)
但是,当我运行此代码时,我从未得到ClosedByInterruptException,一旦输入流关闭,它应该触发.此外,执行阻止调用serial.close() - 因为底层输入流仍然在读取调用上阻塞.我已经尝试用byteChan.close()替换中断调用,然后应该导致AsynchronousCloseException,但是,我得到了相同的结果.
对我所缺少的任何帮助将不胜感激.
您不能将不支持可中断I/O的流InterruptibleChannel
简单地包装成(并且无论如何ReadableByteChannel
都不会扩展InterruptibleChannel
).
你必须看看底层证券的合约InputStream
.SerialPort.getInputStream()
对结果的可中断性有什么看法?如果它没有说什么,你应该假设它忽略了中断.
对于任何未明确支持可中断性的I/O,唯一的选择通常是从另一个线程关闭流.这可能IOException
会AsynchronousCloseException
在对流的调用阻塞的线程中立即引发(尽管可能不是).
然而,即使这非常依赖于InputStream
- 并且底层操作系统的实现也是一个因素.
请注意ReadableByteChannelImpl
返回的类的源代码注释newChannel()
:
private static class ReadableByteChannelImpl
extends AbstractInterruptibleChannel // Not really interruptible
implements ReadableByteChannel
{
InputStream in;
?
Run Code Online (Sandbox Code Playgroud)
RXTX SerialInputStream(serial.getInputStream() 调用返回的内容)支持超时方案,最终解决了我的所有问题。在创建新的 SerialReader 对象之前添加以下内容会导致读取不再无限期地阻塞:
serial.enableReceiveTimeout(1000);
Run Code Online (Sandbox Code Playgroud)
在 SerialReader 对象中,我必须更改一些内容才能直接从 InputStream 读取,而不是创建 ReadableByteChannel,但现在,我可以毫无问题地停止并重新启动读取器。