【问题标题】:How can I make a custom stream collector in java 8 use single thread to do the processing?如何使 java 8 中的自定义流收集器使用单线程进行处理?
【发布时间】:2016-03-29 17:39:15
【问题描述】:

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

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

【问题讨论】:

  • 如果你不希望你的collector被并行使用,你可以在实现combiner的时候抛出异常,但是只要你不报CONCURRENT特性,累加器就会不需要是线程安全的AFAIK。

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


【解决方案1】:

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

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

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

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

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

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

IDENTITY_FINISH 特征将自动添加。

【讨论】:

    猜你喜欢
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 2023-03-17
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多