【发布时间】:2014-09-06 16:04:04
【问题描述】:
我有一个简单的测试应用程序,它连接到 USB 设备(作为本地文件),传输开始传输字符,然后从设备读取输入。这一切都很好,但很少会阻塞 read() 调用。为了防止这种情况,我尝试在继续 read() 操作之前检查是否至少有 1 个可用字节。但是,当我运行它时,我会从 available() 调用中得到一个 IOException。
我的代码是:
public static void testRecord() {
// Records data for a second
String portName = "\\\\.\\<DEVICE_FILE>";
FileWriter out = null;
byte singleByte;
long startTime = System.currentTimeMillis();
try {
out = new FileWriter(portName);
out.write('c'); // start data transmission
out.write(0x0d); // carriage return required
out.flush();
if (out != null)
out.close();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(portName), 512);
System.out.println("Connected to device");
while(System.currentTimeMillis() < startTime+1000) {
avail = bis.available();
if (!(avail > 0)) {
System.out.println("Available: " + avail);
continue;
}
singleByte = (byte) bis.read();
// Do stuff with data
}
if (bis != null)
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("ERROR");
}
}
错误跟踪是:
Connected to device
java.io.IOException
at java.io.FileInputStream.available(Native Method)
at java.io.BufferedInputStream.available(Unknown Source)
at test.Test.testRecord(Test.java:58)
at test.Test.main(Test.java:135)
ERROR
我做错了吗?如果我注释掉 available() 调用,除了它在 read() 上阻塞大约每 50 次运行的问题之外,它可以完美地工作。我还尝试通过 InputStreamReader 将阅读器实现为 BufferedReader(因为数据是 ASCII)并使用 BufferedReader 的 ready() 方法,但总是返回 false。
编辑:我正在寻找在读取之前检查是否有可用数据的替代方法,其中大部分涉及处理阻塞的 read() 调用。我有一个外部线程检查超时,但如果有超时,尝试用 thread.interrupt() 停止线程仍然不会中断阻塞的 read() 调用。同样,从外部线程关闭 InputStream 也不起作用,因为调用仍然被阻塞。我也在这里尝试了https://stackoverflow.com/a/9832633/1020006 的解决方案,但 executor.shutdownNow() 只是 Thread.interrupt() 的包装器,所以也有同样的问题。我想避免使用 Thread.stop(),因为它已被弃用。
我能看到的唯一其他选择是使用可异步中断的 FileChannel 重写读取。
编辑 2:我尝试使用 Thread.stop() 但这也不起作用,正如 Peter Lawrey 在 cmets 中指出的那样,这是系统故障的指示性行为。我设法通过将读取重构为 AsynchronousFileChannel 对象来使其全部工作,该对象从其读取调用返回一个 Future 对象。可以通过 get() 方法中的超时从 Future 获取数据。然后会抛出一个 TimeoutException ,可以捕获该异常以关闭通道。
【问题讨论】:
-
java.io 正在阻塞 API。考虑改用 java.nio,它是非阻塞的
-
你没有做错什么,这可能是一个实现错误。
-
// 用数据做事——你在做什么?确保该流未在该代码中的某处关闭。
-
@ponomandr java.nio 正在阻止文件。 NIO2 是非阻塞的,但实际上它只是阻塞了一个后台线程。
-
我假设您访问的设备不支持此操作。您似乎不需要此操作,因此我会编写您的读取循环以不使用它。
标签: java usb bufferedreader bufferedinputstream