我搜索了我能找到的与PipedInputStreams和PipedOutputStreams有关的所有问题,但没有找到任何可以帮助我的东西。希望这里有人会遇到类似的东西。
背景
我有一个类从任何java.io.InputStream读取数据。该类有一个名为 hasNext()的方法,它检查给定的InputStream是否有数据,如果找到数据则返回true,否则返回false。这个hasNext()方法与其他InputStream完美配合,但是当我尝试使用PipedInputStream(从另一个Thread中的PipedOutputStream提供,封装在下面的inputSupplier变量中)时,它会挂起。在查看hasNext()方法如何工作之后,我使用以下代码重新创建了该问题:
public static void main(String [] args){
PipedInputStream inputSourceStream = new PipedInputStream(inputSupplier.getOutputStream());
byte[] input = new byte[4096];
int bytes_read = inputSourceStream.read(input, 0, 4096);
}
inputSupplier只是我编写的一个小类的实例,它在自己的线程中使用本地PipedOutputStream运行,以避免死锁。
问题 所以,我的问题是hasNext()方法调用流上的PipedInputStream.read()方法,以确定是否有任何数据要读取。这会导致阻塞读取操作永不退出,直到某些数据到达才能读取。这意味着如果流为空,我的hasNext()函数将永远不会返回false(或者根本不会)。
免责声明:我知道available()方法,但所有这些都告诉我,没有可用的字节,而不是我们在流的末尾(可能是Stream的任何实现),所以阅读()需要检查这个。
[编辑] 我最初使用PipedInputStream的目的是模拟“突发”数据源。也就是说,我需要有一个我可以偶尔编写的Stream,看看我的hasNext()方法是否会在读取时检测到Stream上有新数据。如果有更好的方法,那么我会很高兴听到它!
答案 0 :(得分:0)
Java SE 6及更高版本(如果我错了,请纠正我)附带java.nio软件包,该软件包专为异步I / O而设计,听起来就像您所描述的那样
答案 1 :(得分:0)
我讨厌这个旧问题,但这接近谷歌的结果,我刚刚为自己找到了一个解决方案:这个循环字节缓冲区公开了输入和输出流,并且read方法返回当没有数据时立即-1。一点点线程,您的测试类可以按照您想要的方式提供数据。
http://ostermiller.org/utils/src/CircularByteBuffer.java.html
修改强>
原来我误解了上面这个类的文档,当调用read()
的线程被中断时它只返回-1。我快速修改了read方法,它给了我想要的东西(原始代码注释掉了,唯一的新代码是用else
代替else if
:
@Override public int read(byte[] cbuf, int off, int len) throws IOException {
//while (true){
synchronized (CircularByteBuffer.this){
if (inputStreamClosed) throw new IOException("InputStream has been closed; cannot read from a closed InputStream.");
int available = CircularByteBuffer.this.available();
if (available > 0){
int length = Math.min(len, available);
int firstLen = Math.min(length, buffer.length - readPosition);
int secondLen = length - firstLen;
System.arraycopy(buffer, readPosition, cbuf, off, firstLen);
if (secondLen > 0){
System.arraycopy(buffer, 0, cbuf, off+firstLen, secondLen);
readPosition = secondLen;
} else {
readPosition += length;
}
if (readPosition == buffer.length) {
readPosition = 0;
}
ensureMark();
return length;
//} else if (outputStreamClosed){
} else { // << new line of code
return -1;
}
}
//try {
// Thread.sleep(100);
//} catch(Exception x){
// throw new IOException("Blocking read operation interrupted.");
//}
//}
}
```