java - 线程中断未结束对输入流读取的阻塞调用

标签 java multithreading nonblocking channel rxtx

我正在使用 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/O 的流简单地包装到 InterruptibleChannel 中(而且,无论如何,ReadableByteChannel 不会扩展InterruptibleChannel).

你得看看底层InputStream的契约。 SerialPort.getInputStream() 对其结果的可中断性有何看法?如果它什么也没说,您应该假设它忽略了中断。

对于任何不明确支持可中断性的 I/O,唯一的选择通常是从另一个线程关闭流。这可能会在调用流时阻塞的线程中立即引发 IOException(尽管它可能不是 AsynchronousCloseException)。

然而,即使这也非常依赖于 InputStream 的实现——底层操作系统也可能是一个因素。


注意 newChannel() 返回的 ReadableByteChannelImpl 类的源代码注释:

  private static class ReadableByteChannelImpl
    extends AbstractInterruptibleChannel       // Not really interruptible
    implements ReadableByteChannel
  {
    InputStream in;
    ⋮

关于java - 线程中断未结束对输入流读取的阻塞调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3843363/

相关文章:

mongodb - 有没有一个好的库可以让 Kotlin 协程异步访问 Mongo?

c - MPI_Waitsome 失败

java - 为什么将 resizing 设置为 false 会导致出现一些填充?

输入字符串 ""的 java.lang.NumberFormatException

java - android setVisibility(LinearLayout.VISIBLE) 在 WebView @JavascriptInterface 函数中不起作用

c# - C# “async and await”功能和线程

java - java中读取动态文件路径

multithreading - 多线程应用

c# - 运行多个 UI 线程

linux - 在将数据从内核复制到用户期间,非阻塞I/O是否会进入休眠状态?