附录 C 如何以并发方式在同一个流上执行多种操作
Java 8中,流有一个非常大的(也可能是最大的)局限性,使用时,对它操作一次仅能得到一个处理结果。实际操作中,如果你试图多次遍历同一个流,结果只有一个,那就是遭遇下面这样的异常:
java.lang.IllegalStateException: stream has already been operated upon or closed
虽然流的设计就是如此,但我们在处理流时经常希望能同时获取多个结果。譬如,你可能会用一个流来解析日志文件,就像在5.7.3节中所做的那样,而不是在某个单一步骤中收集多个数据。或者,你想要维持菜单的数据模型,就像在第4~6章中用于解释流特性的那个例子,你希望在遍历由“佳肴”构成的流时收集多种信息。
换句话说,你希望一次性向流中传递多个Lambda表达式。为了达到这一目标,你需要一个fork类型的方法,对每个复制的流应用不同的函数。更理想的情况是你能以并发的方式执行这些操作,用不同的线程执行各自的运算得到对应的结果。
不幸的是,这些特性目前还没有在Java 8的流实现中提供。不过,本附录会为你展示一种方法,利用一个通用API 1,即Spliterator,尤其是它的延迟绑定能力,结合BlockingQueues和Futures来实现这一大有裨益的特性。
1本附录接下来介绍的实现基于Paul Sandoz向lambda-dev邮件列表http://mail.openjdk.java.net/pipermail/lambda-dev/2013-November/011516.html提供的解决方案。
