ВНИМАНИЕ: это не дубликат, пожалуйста, прочитайте тему внимательно https://stackoverflow.com/users/3448419/apangin цитата:
Настоящий вопрос заключается в том, почему код иногда работает, когда не должен. Проблема воспроизводится даже без лямбд. Это заставляет меня думать, что может быть ошибка JVM.
В комментариях https://stackoverflow.com/a/53709217/2674303 я попытался выяснить причины поведения кода по разному от начала к другому и участники той дискуссии дали мне совет создать отдельную тему.
Рассмотрим следующий исходный код:
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");
}
}
Иногда (почти всегда) это приводит к тупику.
Пример вывода:
static initializer: main
map: main 2
map: ForkJoinPool.commonPool-worker-3 4
map: ForkJoinPool.commonPool-worker-3 3
map: ForkJoinPool.commonPool-worker-2 0
Но иногда завершается успешно (очень редко):
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
Не могли бы вы объяснить такое поведение?
System.out.println("Finished");
в конец блокаstatic {}
, мы можем ясно показать, что рабочим потокам удалось выполнить тело лямбды, пока инициализация класса еще не завершена, т.е. что это не проблема потока Оп возвращается слишком рано. Обратите внимание, что пример немного неудачен для более новых версий Java, поскольку, начиная с Java 9,count()
пропустит всю обработку и вернет предсказуемый размер. Так что.map(i -> { System.out.println("map: "+Thread.currentThread().getName()+" "+i); return 1; }).sum();
может быть лучше. - person Holger   schedule 11.12.2018sum()
, потому чтоcount()
пропускает обработку (начиная с java 9, как упоминал Хольгер). - person Hulk   schedule 12.12.2018getstatic
/putstatic
, но не дляinvokestatic
. - person apangin   schedule 16.12.2018