printStackTrace()

时间:2015-07-07 11:55:46

标签: exception java.util.scanner printstacktrace

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输出总是按预期或在第二个输出中出现 - 在第二行的开头。

造成这种情况的原因,我该如何解决?

3 个答案:

答案 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?

解决方案:

你应该尝试通过设计你的代码来解决这个问题,在这种情况下无论何时打印它都无关紧要。