从5点起使用Java,今天我在a ::
有人使用列表#foreach
在Java 8中使用 AtomicInteger
。
现在,我想知道这是否可能是必要的 - lo and Chood,请咨询
除非实施类另有指定,否则按迭代顺序执行操作(如果指定了迭代顺序)。
(重点是我的)
...因此,鉴于流
是不是实现 iToble
(从Java 18)的点 - 我应该真的应该真的吗必须假定 Itable
的未知实施者可能会在并行吗?
(如果期望将根据Java版本进行更改,我希望答案可以从8开始处理每个不同版本。)
Using Java since 5, today I encountered an interesting piece of code in a GitHub PR:
Someone used List#forEach
with an AtomicInteger
in Java 8.
Now I wondered whether this could possibly be necessary - and lo and behold, consulting the Java 8 Documentation (where Iterable#forEach
was introduced, as well as the lookalike stream().parallel().forEach
, the latter of which obviously might be parallel) I read:
Unless otherwise specified by the implementing class, actions are performed in the order of iteration (if an iteration order is specified).
(emphasis mine)
... So, given that Stream
makes a point of not implementing Iterable
(as of Java 18) - should I really have to presume that an unknown implementor of Iterable
might do forEach
in parallel?
(If the expectation would have change based on Java version, I'd like an answer to deal with each differing version starting at 8.)
发布评论
评论(1)
请注意,“除非实现类另有指定”的短语已从规范的最新版本:
由于
list
具有定义的遭遇顺序,并在定义的顺序中执行操作,因此我们可以清楚地说,在问题中提到的具体情况下,同时执行被明确排除。The broader question whether
Iterable
'sforEach
precludes concurrent execution of the specified action in general, when there's no defined encounter order, can only be answered by resorting to the 至少令人惊讶的原则,结论是,如果在某些情况下同时执行,则规格应明确提及。据我所知,Java的整个API规范遵守此原则,因此没有理由假设它不适用于此特定方法。最值得注意的是,每个人都知道
stream
API允许并行处理,因为它已得到了重要记录。同样,arrays.parallelsort(…)
启用它。即使是实际的并发收集也适用。例如,当您调用
键()。 //docs.oracle.com/en/java/java/javase/17/docs/api/java.base/java/java/java/util/concurrent/concurrent/package-summary.html#weakly' >迭代策略指定,但同时在呼叫者的线程上依次运行,就像每个方法在另外指定时所做的那样。您需要一个专用
foreach
方法用于并行处理。因此,使用
AtomicInteger
是没有道理的。这是一种普遍的糟糕编程样式,假装功能编程,同时仍然坚持循环思考,使用foreach
并修改功能之外的变量。由于本地变量是不可能的,因此atomicInteger
仅用作int
heap变量的容器。使用单个元素int []
数组也可以做到,但仍然不建议使用。而是保持平原环或
使用实际功能方法,例如
或
Note that the phrase “Unless otherwise specified by the implementing class” has been removed from recent versions of the specification:
Since a
List
has a defined encounter order and performing an action in a defined order precludes concurrent execution, we can clearly say that concurrent execution is precluded explicitly in the specific case mentioned in your question.The broader question whether
Iterable
’sforEach
precludes concurrent execution of the specified action in general, when there’s no defined encounter order, can only be answered by resorting to the Principle of least astonishment, concluding that the specification should mention explicitly if concurrent execution was allowed under certain circumstances. As far as I can see, Java’s entire API specification adheres to this principle, so there’s no reason to assume that it doesn’t apply to this specific method.Most notably, everyone is aware that the
Stream
API allows parallel processing, because it has been prominently documented. Likewise,Arrays.sort(…)
does not permit a surprising parallel evaluation of theComparator
, without mentioning it explicitely, but rather, an explicit use ofArrays.parallelSort(…)
is required to enable it.The same applies even for the actual concurrent collections. E.g. when you call
keySet().forEach(…)
on aConcurrentHashMap
, it will not fail when there are concurrent updates, as the general weakly consistent iteration policy specifies, but also run sequentially on the caller’s thread, as every method does when not specified otherwise. You’d need a dedicatedforEach
method for parallel processing.So the use of
AtomicInteger
is not justified. It’s a widespread bad programming style, pretending functional programming while still being stuck with thinking in loops, usingforEach
and modifying a variable outside the function. Since this is not possible with local variables,AtomicInteger
is only used as container for anint
heap variable here. Using a single elementint[]
array would do as well, but still isn’t recommended. Insteadstay with a plain loop, or
use a real functional approach, e.g.
or