【发布时间】:2014-10-07 07:33:31
【问题描述】:
是否可以从 InputStream 对象创建非阻塞 ReadableByteChannel?
Channel.newChannel(inputStream) - 生成可能被阻塞的 InputStream.read 调用阻塞的通道
【问题讨论】:
是否可以从 InputStream 对象创建非阻塞 ReadableByteChannel?
Channel.newChannel(inputStream) - 生成可能被阻塞的 InputStream.read 调用阻塞的通道
【问题讨论】:
不,这是不可能的。请参阅Javadoc。
【讨论】:
Thread 为代价将阻塞输入通过管道传输到非阻塞通道,但显然这会破坏非阻塞 io 的激励目的(即避免线程)。
您可以尝试自己实现这样的通道,使用“Inputstream.avalable()”来避免阻塞。但是,这种方法并不能保证返回正确的值,所以你必须检查你使用的 Inputstream 实现。
您确定需要非阻塞通道吗?通常,它需要定期轮询以检查数据的到达。在数据到达时调用回调的异步通道更有意义。
【讨论】:
ReadableByteChannel.newChannel 方法
public static ReadableByteChannel newChannel(final InputStream in) {
checkNotNull(in, "in");
if (in instanceof FileInputStream &&
FileInputStream.class.equals(in.getClass())) {
return ((FileInputStream)in).getChannel();
}
return new ReadableByteChannelImpl(in);
}
以及ReadableByteChannelImpl的读取方法
public int read(ByteBuffer dst) throws IOException {
int len = dst.remaining();
int totalRead = 0;
int bytesRead = 0;
synchronized (readLock) {
while (totalRead < len) {
int bytesToRead = Math.min((len - totalRead),
TRANSFER_SIZE);
if (buf.length < bytesToRead)
buf = new byte[bytesToRead];
if ((totalRead > 0) && !(in.available() > 0))
break; // block at most once
try {
begin();
bytesRead = in.read(buf, 0, bytesToRead);
} finally {
end(bytesRead > 0);
}
if (bytesRead < 0)
break;
else
totalRead += bytesRead;
dst.put(buf, 0, bytesRead);
}
if ((bytesRead < 0) && (totalRead == 0))
return -1;
return totalRead;
}
}
所以,它只是调用了InputStream的read方法,以及InputStream的read方法的javadoc:
此方法阻塞,直到输入数据可用,文件结尾是 检测到,或者抛出异常。
因此您可以实现 InputStream 的子类并覆盖读取方法,并将这些方法实现为非阻塞。
【讨论】: