任务是从InputStream读取并等待结果长达可配置的时间。
给出两个选项,哪个更可取?或建议另一个。
对available()的非阻塞调用,您必须使用忙于睡眠的轮询来轮询
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);
}
}
}
答案 0 :(得分:1)
两种方法都有缺陷。使用available()
时,如果出现EOF,您的程序可能会永远挂起。提交阻塞的read()
时,有可能后台调用将在超时后的 中完成并使用流中的数据。因此,数据将丢失。
当流是套接字流时,可以设置套接字超时并在代码中处理SocketTimeoutException
。现代Java还为非套接字I / O类型提供了异步API。您可以调用其返回Future
的方法。但是,如果您决定取消或放弃Future,则该频道可能会标记为不一致,并拒绝进一步操作。
如果是一些旧的第三方API返回了黑盒InputStream,则可以使用我的包装器获得类似套接字的行为。它将您不消耗的字节保存在内部缓冲区中:https://gist.github.com/basinilya/a5392de106cd890a28742960bcc5cf8c