为什么同一个程序的 Exception 和 println() 行每次都以不同的顺序出现?

Why do Exception and println() lines come out in different order each time for the same program?

我在处理我的一个小项目时注意到一些 st运行ge:我在代码中添加了一些 System.out.println(); 行来追踪错误。奇怪的是,当我 运行 来自 IDE 的错误程序时,异常堆栈跟踪的行和其中一些打印语句的打印输出每次程序 运行.常识表明同一个程序 运行 每次都以相同的方式执行,包括例外情况,因此所有执行的输出也必须相同。然而,这种情况并非如此。行的内容保持不变,堆栈跟踪行和打印输出行的顺序保持一致,但它们每次都以不同的方式混合。所以在一个 运行 上,控制台输出是

populatePinArrays: An input pin added to gate!
populatePinArrays: An input pin added to gate!
populatePinArrays: An output pin added to gate!
Exception in thread "main" java.lang.NullPointerException
    at Gates.Pin.isReadyToEvaluate(Pin.java:28)
    at Gates.Pin.evaluate(Pin.java:19)
    at Gates.TheCircuit.evaluateTheCircuit(TheCircuit.java:42)
    at main.Main.main(Main.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
CircEval: all set to dirty
CircEval: all input pins set to clean

下次还可以

Exception in thread "main" populatePinArrays: An input pin added to gate!
populatePinArrays: An input pin added to gate!
java.lang.NullPointerException
populatePinArrays: An output pin added to gate!
CircEval: all set to dirty
CircEval: all input pins set to clean
    at Gates.Pin.isReadyToEvaluate(Pin.java:28)
    at Gates.Pin.evaluate(Pin.java:19)
    at Gates.TheCircuit.evaluateTheCircuit(TheCircuit.java:42)
    at main.Main.main(Main.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

我主要是出于好奇 Java/JVM 细节负责什么以及幕后到底发生了什么,但是如果这件事的发生表明我的程序存在某些缺陷,我想知道。

异常堆栈跟踪被写入 stderr,而您的正常输出被写入 stdout。它们最终都在同一个地方(在这种情况下,并非总是如此),但由于它们不是同一个流,因此它们可能以截然不同的方式交错。

如果您将 System.out.printlns 转换为 System.err.printlns(或使用 e.printStackTrace(System.out); 将堆栈跟踪打印到标准输出),您会发现这种情况不再发生。