CAUTION: it is not a duplicate, please read topic сarefully https://stackoverflow.com/users/3448419/apangin quote:
The real question is why the code sometimes works when it should not. The issue reproduces even without lambdas. This makes me think there might be a JVM bug.
In the comments of https://mcmap.net/q/586287/-deadlock-happens-if-i-use-lambda-in-parallel-stream-but-it-doesn-39-t-happen-if-i-use-anonymous-class-instead-duplicate I tried to find out reasons why code behaves differently from one start to another and participants of that discussion made me piece of of advice to create a separated topic.
Let's consider following source code:
public class Test {
static {
System.out.println("static initializer: " + Thread.currentThread().getName());
final long SUM = IntStream.range(0, 5)
.parallel()
.mapToObj(i -> {
System.out.println("map: " + Thread.currentThread().getName() + " " + i);
return i;
})
.sum();
}
public static void main(String[] args) {
System.out.println("Finished");
}
}
Sometimes(almost always) it leads to deadlock.
Example of output:
static initializer: main
map: main 2
map: ForkJoinPool.commonPool-worker-3 4
map: ForkJoinPool.commonPool-worker-3 3
map: ForkJoinPool.commonPool-worker-2 0
But sometimes it finishes successfully(very rare):
static initializer: main
map: main 2
map: main 3
map: ForkJoinPool.commonPool-worker-2 4
map: ForkJoinPool.commonPool-worker-1 1
map: ForkJoinPool.commonPool-worker-3 0
Finished
or
static initializer: main
map: main 2
map: ForkJoinPool.commonPool-worker-2 0
map: ForkJoinPool.commonPool-worker-1 1
map: ForkJoinPool.commonPool-worker-3 4
map: main 3
Could you explain that behaviour?
System.out.println("Finished");
to the end of thestatic {}
block, we can clearly show that the worker threads managed to execute the lambda body while the class initialization has not completed yet, i.e. that it is not an issue of the stream op returning too early. Note that the example is a bit unfortunate for newer Java versions as starting with Java 9,count()
will skip the entire processing and return the predictable size. So.map(i -> { System.out.println("map: "+Thread.currentThread().getName()+" "+i); return 1; }).sum();
might be better. – Guglielmasum()
, becausecount()
skips the processing (starting with java 9, as Holger mentioned). – Atropinegetstatic
/putstatic
bytecodes, but not forinvokestatic
. – Trabzon