Несоответствие ожидаемому результату работы IntStream
Разбираюсь в многопоточности, дошёл до класса Phaser. Встретил пример.
Phaser phaser = new Phaser();
IntStream.range(0, 3).forEach(i -> {
phaser.register();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " " + phaser);
}).start();
});
Вывод работы этого кода:
Thread-1 java.util.concurrent.Phaser@42b4d62c[phase = 0 parties = 3 arrived = 0]
Thread-0 java.util.concurrent.Phaser@42b4d62c[phase = 0 parties = 3 arrived = 0]
Thread-2 java.util.concurrent.Phaser@42b4d62c[phase = 0 parties = 3 arrived = 0]
Сразу parties = 3 да и ещё в первой строке вывода. Думал будет reg() sout ,reg() sout, reg() sout() и parties = 1, parties = 2, parties = 3.
Искал в интернете(в т.ч. и в англоязычном) - ближе всего объяснение такого поведения в "планировщике", а там зарылся и тупик.
Может в не в ту степь пошёл: пробовал менять местами строки в этом куске кода, чтобы увидеть логику - безрезультатно.
Объясните, откуда программа знала, что parties = 3 до выполнения всего цикла (0,3)?
Ответы (1 шт):
Никакой магии нет. Привыкайте к асинхронности. Есть цикл, который выполняется в главном потоке и делает 2 операции - регистрирует участника и запускает новый поток. Запуск потока (вернее запуск и выполнение его Runnable) операция недешёвая и небыстрая. Тем более основной поток не дожидается самого факта запуска, скидывая эту проблему на JVM, и спокойненько идёт дальше выполнять цикл где снова меняет состояния фазера. К моменту, когда все 3 потока доходят до вывода на консоль, фазер уже зарегистрировал всех участников (ну или почти всех). Чтобы увидеть хронологию происходящего, достаточно расставить временные логи происходящего.
IntStream.range(0, 3).forEach(i -> {
phaser.register();
System.out.println("Register: " + System.nanoTime());
new Thread(() -> {
System.out.println("Output: " + System.nanoTime());
System.out.println(Thread.currentThread().getName() + " " + phaser);
}).start();
});
ну и собственно логи
Register: 2452906851214400
Register: 2452906856518900
Register: 2452906856672000
Output: 2452906856816400
Output: 2452906856921500
Output: 2452906856968400