我有一个管道,其中文件是并行处理的,但是我对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的接收器同步。
最后,我正在寻找一种并行发送状态的方法,有什么想法吗?
答案 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的帮助)