Parallel processing 如何使Java8中的自定义流收集器使用单线程进行处理?

Parallel processing 如何使Java8中的自定义流收集器使用单线程进行处理?,parallel-processing,java-8,java-stream,collectors,Parallel Processing,Java 8,Java Stream,Collectors,一般来说,我正在编写一个自定义流收集器,据我所知,它与一个供应商、一个累加器和一个组合器组合在一起。在我的custome收集器中,我意识到累加器不是线程安全的,所以我将合并器设置为null,收集器。特性设置为IDENTITY\u FINISH。代码可以通过编译,但存在运行时异常,因为组合器不应为null,这已由NotNull注释指示 我的问题是,如果我在收集器中提供了一个带收集器的组合器。特征是IDENTITY\u FINISH,那么累加器是并行运行还是并发运行,还是仅在一个线程中运行而没有争用

一般来说,我正在编写一个自定义流收集器,据我所知,它与一个供应商、一个累加器和一个组合器组合在一起。在我的custome收集器中,我意识到累加器不是线程安全的,所以我将合并器设置为null,收集器。特性设置为IDENTITY\u FINISH。代码可以通过编译,但存在运行时异常,因为组合器不应为null,这已由NotNull注释指示

我的问题是,如果我在收集器中提供了一个带收集器的组合器。特征是IDENTITY\u FINISH,那么累加器是并行运行还是并发运行,还是仅在一个线程中运行而没有争用问题?

对于收集器中使用的任何函数,包括供应商、累加器、组合器和完成器,都不能使用null。当您无法提供合适的组合器时,通常的解决方案是通过一个抛出lambda:

(a, b) -> {throw new UnsupportedOperationException("Combining is not supported");}
之后,您可以使用收集器。尽管这仍然是一种糟糕的做法,因为收集器接口不允许不实现合并器

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

最后请注意,如果没有finisher,则不需要显式指定IDENTITY\u FINISH。只用

Collector<?,?,?> myCollector = Collector.of(mySupplier, myAccumulator, myCombiner);
标识完成特性将自动添加。

对于收集器中使用的任何函数,包括供应商、累加器、合路器和修整器,不能使用null。当您无法提供合适的组合器时,通常的解决方案是通过一个抛出lambda:

(a, b) -> {throw new UnsupportedOperationException("Combining is not supported");}
之后,您可以使用收集器。尽管这仍然是一种糟糕的做法,因为收集器接口不允许不实现合并器

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

最后请注意,如果没有finisher,则不需要显式指定IDENTITY\u FINISH。只用

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

标识\u FINISH特性将自动添加。

如果不希望收集器并行使用,可以在实现合并器时引发异常,但只要不报告并发特性,累加器不需要是线程安全的AFAIK。如果不希望并行使用收集器,可以在实现合并器时引发异常,但只要不报告并发特性,累加器就不需要是线程安全的AFAIK。