printStackTrace()
就像在等待输入后在自己的线程中运行一样。这是我的代码:
try {
new Scanner(System.in).nextLine();
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
System.out.print("STUFF");
我有时得到预期的输出(最后有STUFF
),但有时候我会得到这个:
blabla // the scanner input
java.lang.ExceptionSTUFF
at Test.main(Test.java:7)
有时这个:
blabla
java.lang.Exception
STUFF at Test.main(Test.java:7)
用System.in.read()
替换扫描仪会产生相同的结果。完全删除线会产生预期的结果。在我注意到这个问题的实际程序中,堆栈跟踪要长得多,并且STUFF
输出总是按预期或在第二个输出中出现 - 在第二行的开头。
造成这种情况的原因,我该如何解决?
答案 0 :(得分:3)
printStackTrace
,根据文档prints to the standard error stream:
public void printStackTrace() - 将此throwable及其回溯打印到标准错误流。
...这是System.err
。然后你写信给System.out
。这两个是不同的流,因此在不同的时间刷新到实际输出。保持代码原样,它等同于this question中列出的问题。
要解决此问题,您可以手动刷新输出流,也可以将例外打印到System.out
而不是System.err
。您可以将variant of printStackTrace that accepts a PrintStream
标准输出用作参数:e.printStackTrace(System.out);
答案 1 :(得分:0)
这是将东西打印到控制台的本质。所有内容,标准输出,标准错误等都会被打印出来打印到控制台,但由于java本身就是多线程的,因此无法保证将这些项目的顺序添加到队列中进行打印。
多线程可以做很时髦的事情!
答案 2 :(得分:0)
这实际上并不是一种奇怪的行为; Java旨在以这种方式工作。在大多数情况下,它是我们都喜欢的功能,它使我们的代码比我们实际编写的代码运行更高效。它的意思是JVM旨在将我们的代码重新排列和优化为更好的字节代码,而不仅仅是凡人开发人员甚至可以为实现这一目标而烦恼。
你可以看一下这个; Java是一种我们正在使用的代码框架,它将以尽可能最有效的方式完成我们想要的代码(至少已编程)。 Java API是我们正在使用的Java框架的API。
并将其与您的代码联系起来;你正在初始化两个流,两个缓冲流,一个是System.out
,一个是printStackTrace()
。当您执行代码时,Java将重新安排您的代码并将其线程化为最佳运行,就像Java可以实现的那样。这意味着首先完成的流将首先打印到控制台。
Java在被打印的内容中没有价值,这是我们人类拥有的价值;我们倾向于以特殊订单阅读东西。这就是为什么Java对我们的开发人员来说是一个挑战,他们要编写线程安全的代码,而这些代码在执行时并不关心;给定相同的输入,它应该总是返回相同的输出。
由于您的System.out
流的打印速度比堆栈跟踪流快,因此它们可能始终在堆栈跟踪之前打印,因为它们是缓冲流。缓冲流需要时间来缓冲,这既是线程化的又是耗时的。为什么Java不应该为您提供首先完成的流并释放该线程和CPU?
你应该尝试通过设计你的代码来解决这个问题,在这种情况下无论何时打印它都无关紧要。