通常,我正在编写一个自定义流收集器,它与供应商,累加器和组合器相结合,据我所知。在我的客户收集器中,我意识到累加器不是线程安全的,因此我将组合器设置为null
而Collector.Characteristics
设置为IDENTITY_FINISH
。代码可以通过编译,但是存在运行时异常,因为组合器不应该为null,这已经由NotNull注释指示。
我的问题是,如果我在Collector.Characteristics
为IDENTITY_FINISH
的收集器中提供合并器,累加器是并行(或同时)运行还是只在单个线程中运行而没有竞争问题?
答案 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
特征将自动添加。