基于重复的jOOλ流的多线程

时间:2016-12-12 09:07:51

标签: multithreading java-8 java-stream

下面的代码代表了我试图解决的问题的玩具示例。

想象一下,我们有一个原始数据流originalStream,目标是应用2个非常不同的数据处理。作为一个例子,一个数据处理将每个元素乘以2并对结果求和(dataProcess1),另一个将乘以4并求结果(dataProcess2)。显然,现实生活中的操作不会那么简单....

想法是使用jOOλ来复制流并将两个操作应用于2个流。但是,诀窍在于我想在不同的线程中运行两种数据处理。由于originalStream.duplicate()不是开箱即用的线程安全,因此下面的代码将无法给出正确的结果: result1 = 570; result2 = 180 。相反,代码可能无法预测在NPE上失败,产生错误的结果或(有时)甚至给出正确的结果......

问题是如何最低限度地修改代码,使其成为线程安全的。

注意我不想先将流收集到列表中,然后生成2个新流。相反,我希望继续使用流,直到最终在数据流程结束时收集它们。它可能不是最有效也不是最合乎逻辑的事情,但我认为它在概念上很有趣。 请注意我希望继续使用org.jooq.lambda.Seq group:'org.jooq',名称:'jool',版本:'0.9.12')尽可能多,因为真正的数据处理函数将使用特定于此库的方法,而不会出现在常规Java流中。

Seq<Long> originalStream = seq(LongStream.range(0, 10));
Tuple2<Seq<Long>, Seq<Long>> duplicatedOriginalStream = originalStream.duplicate();

ExecutorService executor = Executors.newFixedThreadPool(2);
List<Future<Long>> res = executor.invokeAll(Arrays.asList(
    () -> duplicatedOriginalStream.v1.map(x -> 2 * x).zipWithIndex().map(x -> x.v1 * x.v2).reduce((x, y) -> x + y).orElse(0L),
    () -> duplicatedOriginalStream.v2.map(x -> 4 * x).reduce((x, y) -> x + y).orElse(0L)
));
executor.shutdown();

System.out.printf("result1 = %d\tresult2 = %d\n", res.get(0).get(), res.get(1).get());

0 个答案:

没有答案