use*_*860 15 java thread-local java-8 java-stream
规范是否保证顺序 Java Streams 上的所有操作都在当前线程中执行?("forEach"和"forEachOrdered"除外)
我明确要求规范,而不是当前的实现.我可以自己查看当前的实现,不需要打扰你.但实现可能会改变,还有其他实现.
我问因为ThreadLocals:我使用的是一个内部使用ThreadLocals的Framework.即使像company.getName()这样的简单调用最终也会使用ThreadLocal.我无法改变该框架的设计方式.至少不在理智的时间内.
这里的规范似乎令人困惑.包"java.util.stream"的文档说明:
如果行为参数确实有副作用,除非明确说明,否则不能保证这些副作用对其他线程的可见性,也不保证同一流管道中"相同"元素的不同操作在同一个线程中执行.
...
即使当管道被约束以产生结果,其与流源的遭遇顺序一致(例如,IntStream.range(0,5).parallel()地图(X - > X*2).toArray( )必须产生[0,2,4,6,8]),不能保证制成,以作为对于所述映射器函数被应用到各个元件,或为了在什么螺纹任何行为参数被执行对于给定的元件.
我将其解释为:流上的每个操作都可以在不同的线程中发生.但是"forEach"和"forEachOrdered"的文档明确指出:
对于任何给定元素,可以在任何时间以及库选择的任何线程中执行该动作.
如果每个流操作都可能发生在未指定的线程中,那么该语句将是多余的.因此恰恰相反:串行流上的所有操作都保证在当前线程中执行,除了"forEach"和"forEachOrdered"?
我搜索了关于"Java","Stream"和"ThreadLocal"组合的权威答案,但没有发现任何内容.该关闭的事情是由一个答案作者Brian Goetz在这里对堆栈溢出一个相关的问题,但它是有关订单,而不是线程,它只是对"的forEach",而不是其他流的方法:是否Stream.forEach尊重遇到顺序流的顺序?
我相信您正在寻找的答案没有那么明确的定义,因为它将取决于消费者和/或分离器及其特征:
在阅读主要引用之前:
https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#stream
default Stream stream() 返回以此集合作为源的顺序 Stream。当 spliterator() 方法无法返回 IMMUTABLE、CONCURRENT 或后期绑定的 spliterator 时,应重写此方法。(有关详细信息,请参阅 spliterator()。)
https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html#binding
尽管它们在并行算法中具有明显的实用性,但分割器预计不会是线程安全的;相反,使用 spliterator 的并行算法的实现应确保 spliterator 一次仅由一个线程使用。这通常很容易通过串行线程限制来实现,这通常是通过递归分解工作的典型并行算法的自然结果。调用 trySplit() 的线程可以将返回的 Spliterator 移交给另一个线程,而另一个线程又可以遍历或进一步拆分该 Spliterator。如果两个或多个线程在同一个分裂器上同时操作,则分裂和遍历的行为是未定义的。如果原始线程将 spliterator 交给另一个线程进行处理,则最好在使用 tryAdvance() 消耗任何元素之前进行切换,因为某些保证(例如 SIZED spliterator 的estimateSize() 的准确性)才有效在遍历开始之前。
分裂者和消费者都有自己的一套特征,这将定义保证。假设您正在流中操作。由于分割器应该不是线程安全的,并且应该处理可能位于其他线程中的其他分割器的元素,无论是否是顺序的,因此保证为空。但是,如果没有发生拆分,引号将导致以下结果:在一个拆分器下,操作将保留在同一线程中,任何导致拆分的事件都将导致假设为空,否则为 true
| 归档时间: |
|
| 查看次数: |
264 次 |
| 最近记录: |