如何在java 8中创建自定义流收集器使用单线程来进行处理?

时间:2016-03-29 17:39:15

标签: parallel-processing java-8 java-stream collectors

通常,我正在编写一个自定义流收集器,它与供应商,累加器和组合器相结合,据我所知。在我的客户收集器中,我意识到累加器不是线程安全的,因此我将组合器设置为nullCollector.Characteristics设置为IDENTITY_FINISH。代码可以通过编译,但是存在运行时异常,因为组合器不应该为null,这已经由NotNull注释指示。

我的问题是,如果我在Collector.CharacteristicsIDENTITY_FINISH的收集器中提供合并器,累加器是并行(或同时)运行还是只在单个线程中运行而没有竞争问题?

1 个答案:

答案 0 :(得分:4)

您不能将null用于收集器中使用的任何功能(包括供应商,累加器,组合器和修整器)。当你无法提供合适的组合器时,常见的解决办法就是传递一个投掷lambda:

(a, b) -> {throw new UnsupportedOperationException("Combining is not supported");}

之后,您可以使用Collector。虽然这仍然是不好的做法,因为Collector接口不允许不实现组合器。

请注意,除非您明确指定CONCURRENT特性,否则无需担心线程安全问题。如果您的收集器不是并发的,并行流将在单独的线程中调用供应商,然后在那里独立使用累加器,最后只有在所有累积完成后才调用组合器。这是收集器的全部要点:保证对于非并发收集器,您不需要线程安全,不会执行与同一容器的并发操作。这就是为什么供应商是必要的:可以多次调用它来为每个线程创建几个独立的容器。

最后请注意,如果您没有修整器,则无需明确指定IDENTITY_FINISH。只需使用

Collector<?,?,?> myCollector = Collector.of(mySupplier, myAccumulator, myCombiner);

IDENTITY_FINISH特征将自动添加。