窥视并行流以递增计数器

时间:2018-08-13 23:35:05

标签: java-8 java-stream

我有一个管道,其中文件是并行处理的,但是我对peek函数有点怀疑。

File file = articles.parallelStream( )
                    .map( article -> {
                        String fileName = processer.getFriendlyName( article, locale );
                        currentCount.incrementAndGet();
                        return new ImmutablePair<>( fileName, converted );
                    } )
                    .peek( pair -> statusMessageSender.sendStatusMessage( totalCount, currentCount.get(), pair.getKey( ) ) )
                    .collect( new Archiver( archivePath ) );

通过阅读javadocs,我不能完全确定应该发送当前进度状态的计数器是否在执行其工作(基本上是在此处的文档中寻找保证)

  

对于并行流管道,可以在任何位置调用该动作   时间和元素在任何线程中都可以通过   上游操作。

在我看来,无论文件名相对于处理顺序是否正确,观察者都将获得当前计数,这很好。但是最终,我走在一条不信任窥视的道路上,并导致sendStatusMessage的接收器同步。

最后,我正在寻找一种并行发送状态的方法,有什么想法吗?

1 个答案:

答案 0 :(得分:0)

最初,讨论中有很多关于偷看的内容,以及为什么我要从映射表达式中分离出消息传递部分。这更多是风格问题,因为我倾向于使用映射函数进行映射,仅此而已。

我能理解为什么人们会捍卫偷看或反对偷看。但是按钮行会消耗一个值并将其传递到管道中。因此,当我正在寻找附带行为(传递消息)时,偷看功能似乎很完美。

在并行流中,问题在于无法预测何时实际调用peek。但是要考虑两个方面:何时发送消息与手头的问题无关,并且消息本身可以随时发送。

最后,计数器也可能处于偷看状态,而消息接收器是这里唯一的真实因素。消息接收者可以有自己的计数器,也可以只考虑时间范围内接收到的最高值。

按钮行,这个问题始于有关peek的建议,最后是以下内容: 在功能方面,偷看功能可以很好地完成其工作:主要是因为管道中的顺序未排序。

但是消息使用者会告诉它是否可以正确使用该消息。鉴于只有一个使用者正在使用此信息,而其他使用者没有使用该信息,最终结论是我们在协议设计中存在问题,而不是偷窥功能。我们从std消息中删除了计数器,问题就消失了。可以安全地使用peek解决此问题,是的,但是可以...

所以: 可能是:

File archive = articles.parallelStream( )
                       .map( article -> {
                           File converted = converter.getFile( ... );
                           String fileName = converter.getFriendlyName( ... );
                           return new ImmutablePair<>( fileName, converted );
                       } )
                       .peek( pair -> statusMessageSender.sendStatusMessage( pair.getKey() ) )
                       .collect( new Archiver( archivePath, deleteArchivedFiles ) );

或:

File archive = articles.parallelStream( )
                       .map( article -> {
                           File converted = converter.getFile( ... );
                           String fileName = converter.getFriendlyName( ... );
                           return new ImmutablePair<>( fileName, converted );
                       } )
                       .peek( pair -> statusMessageSender.sendStatusMessage( currentCount.incrementAndGet(), pair.getKey() ) )
                       .collect( new Archiver( archivePath, deleteArchivedFiles ) );

但是最终,它只是关于协议而不是偷看。可以肯定地使用peek,并且问题的无序性质是可以使用它的原因。 (感谢您对SO的帮助)