Java 从InputStream读取-忙等待时无阻塞与超时时阻塞?
任务是从InputStream读取数据,并在可配置的时间内等待结果 有两种选择,哪一种更可取?或者建议另一个Java 从InputStream读取-忙等待时无阻塞与超时时阻塞?,java,inputstream,blocking,nonblocking,Java,Inputstream,Blocking,Nonblocking,任务是从InputStream读取数据,并在可配置的时间内等待结果 有两种选择,哪一种更可取?或者建议另一个 阻止对read()方法的调用,您必须自己超时 对available()的非阻塞调用,您必须使用忙等待和睡眠来轮询该调用 import java.io.IOException; import java.io.InputStream; import java.util.concurrent.*; public class MyClass { public static void
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.*;
public class MyClass {
public static void main(String[] args) throws InterruptedException, ExecutionException, IOException {
MyClass myClass = new MyClass();
final InputStream in = System.in;
final long timeout = 1000;
final int result = myClass.blockingWithTimeout(in, timeout);
// final int result = myClass.nonBlockingBusyWait(in, timeout);
System.out.println("Result " + result);
}
public int nonBlockingBusyWait(final InputStream is, long timeoutMs) throws IOException, InterruptedException {
final long start = System.currentTimeMillis();
while (is.available() == 0 && (System.currentTimeMillis() < start + timeoutMs)) {
Thread.sleep(1);
}
if (is.available() == 0) {
return -1;
} else {
return is.read();
}
}
public int blockingWithTimeout(final InputStream is, long timeoutMs) throws InterruptedException, ExecutionException {
ExecutorService es = Executors.newSingleThreadExecutor();
Future<Integer> future = es.submit((Callable<Integer>) is::read);
try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
return -1;
} catch (InterruptedException | ExecutionException e) {
throw e;
} finally {
future.cancel(true);
}
}
}
import java.io.IOException;
导入java.io.InputStream;
导入java.util.concurrent.*;
公共类MyClass{
公共静态void main(字符串[]args)引发InterruptedException、ExecutionException、IOException{
MyClass MyClass=新的MyClass();
最终输入流输入=System.in;
最终长超时=1000;
最终int结果=myClass.blockingWithTimeout(in,timeout);
//最终int结果=myClass.nonBlockingBusyWait(in,超时);
系统输出打印项次(“结果”+结果);
}
public int nonBlockingBusyWait(最终输入流为,long-timeoutMs)抛出IOException、InterruptedException{
最终长启动=System.currentTimeMillis();
而(is.available()==0&&(System.currentTimeMillis()
这两种方法都有缺陷。使用
available()
时,如果发生EOF,程序可能会永久挂起。提交阻塞read()
时,后台调用有可能在超时后完成并使用流中的数据。因此,数据将丢失
当流是套接字流时,可以设置套接字超时并在代码中处理SocketTimeoutException
。现代Java还为非套接字I/O类型提供异步API。您可以调用它的方法返回Future
。但是,如果您决定取消或放弃未来,该频道可能会被标记为不一致,并拒绝进一步操作
如果是某个旧的第三方API返回blackbox InputStream,您可以使用我的包装器获得类似套接字的行为。它会将不使用的字节保存在内部缓冲区中:不要使用
available()
。在EOFDon的情况下,这是标准未指定的行为。我永远不会比较currentTimeMillis()
。始终减去截止日期并与零进行比较。