Java:合并InputStreams

时间:2010-10-14 08:02:08

标签: java multithreading merge inputstream

我的目标是创建(或使用现有的)InputStream实现(比如MergeInputStream),它将尝试从多个InputStream中读取并返回第一个结果。之后,它将释放锁定并停止从所有InputStreams读取,直到下一次mergeInputStream.read()调用。我很惊讶我没有找到任何这样的工具。问题是:所有的源InputStream都不是很有限(例如,不是文件,而是System.in,socket等),所以我不能使用SequenceInputReader。我知道这可能需要一些多线程机制,但我完全不知道如何做到这一点。我尝试谷歌但没有结果。

2 个答案:

答案 0 :(得分:3)

优先使用SelectableChannelSelector 解决从多个来源读取输入并将其序列化为一个流的问题。然而,这要求所有源都能够提供可选择的信道。这可能是也可能不是。

如果可选择的频道不可用,您可以通过让读取实现执行以下操作来选择使用单个线程解决:对于每个输入流is,请检查{是否{ {1}},若然,则返回is.available() > 0。重复此过程,直到某些输入流有可用数据。

然而,这种方法有两个主要缺点:

  1. Not all implementations of is.read()以某种方式实现InputStream,当且仅当{ {1}}会阻止。结果是,即使available()将返回一个值,也可能无法从此流中读取数据。这是否被视为一个错误是值得怀疑的,因为文档只是声明它应该返回可用字节数的“估计”。

  2. 它使用了一个所谓的“忙循环”,这基本上意味着你要么需要在循环中进入睡眠状态(导致读取延迟),要么不必要地占用CPU。

  3. 您的第三个选择是通过为每个输入流生成一个线程来处理阻塞读取。但是,如果要读取大量输入流,则需要仔细同步并可能需要一些开销。下面的代码是第一次尝试解决它。我无法确定它是否已充分同步,或者它以最佳方式管理线程。

    read()

答案 1 :(得分:1)

我可以想到三种方法:

  • 使用非阻塞I / O(API documentation)。这是最干净的解决方案。
  • 多个线程,每个合并的输入流一个。线程将阻塞相关输入流的read()方法,然后在数据可用时通知MergeInputStream对象。 read()中的MergedInputStream方法会等待此通知,然后从相应的流中读取数据。
  • 繁忙循环的单线程。您的MergeInputStream.read()方法需要循环检查每个合并输入流的available()方法。如果没有可用数据,请睡几毫秒。重复,直到其中一个合并输入流中的数据可用。