繁体   English   中英

从 InputStream 读取 - 非阻塞忙等待 VS 阻塞超时?

[英]Reading from InputStream - non-blocking with busy waiting VS blocking with timeout?

任务是从 InputStream 中读取数据并等待结果达到可配置的时间。

给定两种选择,哪一种更可取? 或者推荐另一个。

  1. 阻塞调用 read() 方法,您必须自己超时
  2. 对可用()的非阻塞调用,您必须使用忙等待和睡眠进行轮询

    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); } } }

这两种方法都有缺陷。 使用available()您的程序可能会在 EOF 的情况下永远挂起。 提交阻塞read() ,后台调用有可能在超时完成并消耗流中的数据。 因此数据会丢失。

当您的流是套接字流时,您可以在代码中设置套接字超时并处理SocketTimeoutException 现代 Java 还为非套接字 I/O 类型提供异步 API。 你可以调用它的方法返回Future 但是,如果您决定取消或放弃 Future,则该频道可能会被标记为不一致并拒绝进一步操作。

如果它是一些旧的 3rd 方 API,它返回一个黑盒 InputStream,你可以使用我的包装器来获得类似套接字的行为。 它节省了您在内部缓冲区中不消耗的字节: https : //gist.github.com/basinilya/a5392de106cd890a28742960bcc5cf8c

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM