Вы не можете предсказать результат многопоточности.
Он может отличаться, если вы запускаете свой код на другом устройстве или несколько раз.
Вы не можете (или не должны) полагаться на время или планировщик.
Я думаю, что параллелизм / энергонезависимость сама по себе может быть не единственной проблемой, но вы также можете принять во внимание промывку:
x=3 (ThreadExample(1))
sysout 3 (ThreadExample(1))
syserr x (main thread)
x=1 (ThreadExample(2))
sysout 3 (ThreadExample (2))
flush stdout (caused by jvm exit)
flush stderr (caused by jvm exit)
Обратите внимание на грипп sh в конце. stdout и stderr не могут быть синхронизированы.
Эти потоки буферизуются и записываются в консоль в любое время.
Хотя две вещи, записанные в stdout или stderr, гарантированно будут записаны в правильном порядке , это не гарантировано, если вы отправляете одно в стандартный вывод, а другое в стандартный поток.
Также гарантируется, что все, что напечатано в stdout
и stderr
, записывается, когда jvm завершается нормально (нет kill -9
или аналогичный).
Если jvm пишет stdout
перед stderr
, вы можете получить свой результат.
Если вы хотите, чтобы выходные данные печатались правильно, вы можете сделать две вещи:
Вызвать flush
вручную после печати
создайте блок synchronized
(или аналогичный) вокруг операции, println
и flush
. (Обратите внимание, что при этом вы можете немного потерять производительность / параллелизм)
Если вы хотите проверить, имеет ли промывка значение в вашем случае, добавьте System.err.flush();
(чтобы stderr
сбрасывается перед stdout
) в конце вашей профраммы и посмотрите, есть ли разница.
Кроме того, есть еще кое-что, чего я не нашел в других ответах, а именно: оптимизация JIT.
Компилятор JIT может оптимизировать вашу программу. Например, он может оптимизировать:
x=3;
System.out.println(x);
до:
x=3;
System.out.println(3);
, чтобы печатать 3
, даже если это не 3
в то время, когда println
называется.