Java PipedInputStream available()方法返回值
我正在尝试编写一段解锁代码,以便从数据库读取。在调用阻塞读取API之前,它基本上会检查是否有任何内容需要读取:Java PipedInputStream available()方法返回值,java,inputstream,pipe,Java,Inputstream,Pipe,我正在尝试编写一段解锁代码,以便从数据库读取。在调用阻塞读取API之前,它基本上会检查是否有任何内容需要读取: int n = 0; if ((n = pipedInputStream_.available()) > 0) { pipedInputStream_.read(...) } 通过阅读,我无法确定该检查应该是什么,因为可能的值为零(表示没有数据,或关闭/中断流)或大于零。那么,打电话的人怎么知道有什么东西要读呢 返回可以不阻塞地从此输入流读取的字节数,如果此输入流已通
int n = 0;
if ((n = pipedInputStream_.available()) > 0) {
pipedInputStream_.read(...)
}
通过阅读,我无法确定该检查应该是什么,因为可能的值为零(表示没有数据,或关闭/中断流)或大于零。那么,打电话的人怎么知道有什么东西要读呢
返回可以不阻塞地从此输入流读取的字节数,如果此输入流已通过调用其close()方法关闭,或者管道未连接或已断开,则返回0
从源代码看,似乎只有值为零或大于零
public synchronized int available() throws IOException {
if(in < 0)
return 0;
else if(in == out)
return buffer.length;
else if (in > out)
return in - out;
else
return in + buffer.length - out;
}
public synchronized int available()引发IOException{
if(in<0)
返回0;
else if(in==out)
返回缓冲区长度;
否则如果(输入>输出)
返回输入输出;
其他的
返回in+buffer.length-out;
}
如果available()
返回零,则当前没有可读取的字节。根据您所引用的文档,这可能是因为以下几个原因:
- 管道是封闭的
- 管子断了
- 所有以前可用的输入(如果有)都已使用
available()
中的零返回值可能意味着发生了错误,这意味着您将来将无法通过管道读取更多数据,但在这里无法确定,因为零可能表示上面的第三种情况,即在InputStream#read()上阻塞
最终可能会产生更多的数据,相应的OutputStream
端将通过管道推送这些数据
在有更多数据可用之前,我不认为可以使用available()
轮询PipedInputStream
,因为您永远无法区分上面的终端情况(第一个和第二个)和读卡器比写卡器更饿。像许多流接口一样,在这里您也必须尝试使用并准备失败。这就是陷阱InputStream#read()
将被阻止,但直到您在尝试读取时承诺阻止,您才能发现不再有输入
将消费行为建立在
available()
上是不可行的。如果它返回一个正数,则有一些内容需要阅读,但当然,即使是现在可用的内容也可能“不足以”满足您的消费者。如果您以阻塞方式提交一个线程来使用InputStream
,并使用available()
跳过轮询,那么您的应用程序将更易于管理。让InputStream#read()
成为您在这里的唯一oracle。我需要一个过滤器来拦截慢速连接,我需要尽快关闭DB连接,所以我最初使用Java管道,但仔细看它们的实现时,它都是同步的,所以我最终创建了我自己的QueueInputStream,使用一个小缓冲区和阻塞队列将缓冲区放入队列。一旦缓冲区满了,它是无锁的,除了LinkedBlockingQueue使用的锁条件,在小缓冲区的帮助下,它应该是便宜的,此类仅用于每个实例的单个生产者和消费者:
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.*;
public class QueueOutputStream extends OutputStream
{
private static final int DEFAULT_BUFFER_SIZE=1024;
private static final byte[] END_SIGNAL=new byte[]{-1};
private final BlockingQueue<byte[]> queue=new LinkedBlockingDeque<>();
private final byte[] buffer;
private boolean closed=false;
private int count=0;
public QueueOutputStream()
{
this(DEFAULT_BUFFER_SIZE);
}
public QueueOutputStream(final int bufferSize)
{
if(bufferSize<=0){
throw new IllegalArgumentException("Buffer size <= 0");
}
this.buffer=new byte[bufferSize];
}
private synchronized void flushBuffer()
{
if(count>0){
final byte[] copy=new byte[count];
System.arraycopy(buffer,0,copy,0,count);
queue.offer(copy);
count=0;
}
}
@Override
public synchronized void write(final int b) throws IOException
{
if(closed){
throw new IllegalStateException("Stream is closed");
}
if(count>=buffer.length){
flushBuffer();
}
buffer[count++]=(byte)b;
}
@Override
public synchronized void close() throws IOException
{
flushBuffer();
queue.offer(END_SIGNAL);
closed=true;
}
public Future<Void> asyncSendToOutputStream(final ExecutorService executor, final OutputStream outputStream)
{
return executor.submit(
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
try{
byte[] buffer=queue.take();
while(buffer!=END_SIGNAL){
outputStream.write(buffer);
buffer=queue.take();
}
outputStream.flush();
} catch(Exception e){
close();
throw e;
} finally{
outputStream.close();
}
return null;
}
}
);
}
}
import java.io.IOException;
导入java.io.OutputStream;
导入java.util.concurrent.*;
公共类QueueOutputStream扩展了OutputStream
{
私有静态final int DEFAULT_BUFFER_SIZE=1024;
私有静态最终字节[]END_信号=新字节[]{-1};
private final BlockingQueue=新建LinkedBlockingDeque();
专用最终字节[]缓冲区;
私有布尔闭合=假;
私有整数计数=0;
公共队列输出流()
{
该值(默认缓冲区大小);
}
公共QueueOutputStream(最终int-bufferSize)
{
if(bufferSize0){
最终字节[]复制=新字节[计数];
System.arraycopy(缓冲区,0,拷贝,0,计数);
报价单(复印件);
计数=0;
}
}
@凌驾
公共同步的无效写入(最终int b)引发IOException
{
如果(关闭){
抛出新的IllegalStateException(“流已关闭”);
}
如果(计数>=缓冲区长度){
flushBuffer();
}
缓冲区[计数++]=(字节)b;
}
@凌驾
public synchronized void close()引发IOException
{
flushBuffer();
排队报盘(结束信号);
关闭=真;
}
公共未来asyncSendToOutputStream(最终执行器服务执行器,最终输出流OutputStream)
{
返回执行者。提交(
新的可调用()
{
@凌驾
public Void call()引发异常
{
试一试{
byte[]buffer=queue.take();
while(缓冲区!=结束信号){
outputStream.write(缓冲区);
buffer=queue.take();
}
outputStream.flush();
}捕获(例外e){
close();
投掷e;
}最后{
outputStream.close();
}
返回null;
}
}
);
}
}
0并不意味着流已关闭或中断。根据规范,零或大于零是唯一允许的结果。您能否澄清为什么说零并不意味着关闭或断流?请看seh的解释,我同意。Java文档还说:“返回:可以从该输入流中读取而不阻塞的字节数,或者如果该输入流已通过调用其close()方法关闭,或者如果管道未连接或已断开,则返回0。”您误解了。零表示在没有阻塞的情况下没有要读取的数据,或者流已关闭,或者管道未连接,或者管道已断开。这不仅仅意味着其中一种情况,当然。附件消除了第一个sta引起的混乱