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输出总是像预期的那样出现,或者出现在上面的第二个输出中--在第二行的开头。
是什么原因造成的,我怎么解决呢?
发布于 2015-07-07 12:03:19
printStackTrace,根据文档,打印到标准错误流
public void printStackTrace() --打印此可抛出并将其回溯到标准错误流。
...which是System.err。然后你写信给System.out。这两者是不同的流,因此在不同的时间被冲到实际的输出。保持代码的原样,它等同于这个问题中概述的问题。
要解决此问题,可以手动刷新输出流,也可以将异常打印到System.out而不是System.err。您可以使用标准输出的PrintStream作为参数:e.printStackTrace(System.out);
发布于 2015-07-07 12:55:26
这实际上一点也不奇怪;Java就是这样设计的。在大多数情况下,这是一个我们都喜欢的特性,它使我们的代码比我们实际编写的代码运行得更高效。“它”所指的是,JVM的设计目的是将我们的代码重新排列并优化成更好的字节代码,这比我们普通的开发人员甚至试图实现的还要麻烦。
您可以这样看待它;Java是我们在代码中使用的一种框架,它将以尽可能高效的方式(至少是用它编写的)来完成我们希望它做的事情。Java是我们使用的Java框架的API。
为了将其与代码联系起来,您正在初始化两个流,两个缓冲流,一个是System.out,一个是printStackTrace()。当您执行您的代码时,Java将重新安排您的代码并将其线程化,使其尽可能地优化运行。这意味着流首先完成的内容将被打印到控制台。
Java在打印什么时候没有价值,这是我们人类拥有的一个值;我们更喜欢按特殊顺序阅读东西。这就是为什么Java对于我们开发人员来说是一个挑战,他们不关心何时执行线程安全代码;对于相同的输入,Java应该总是返回相同的输出。
由于您的System.out流比堆栈跟踪流的打印速度更快,所以它可能总是在堆栈跟踪之前打印,因为它们是缓冲的流。缓冲流需要时间来缓冲,这既是线程,也是不同的时间消耗。为什么Java不给您先完成的流,并释放线程和CPU?
解决方案:
您应该尝试通过设计您的代码以一种不重要的方式来解决这一问题--在什么时候打印它。
发布于 2015-07-07 12:02:01
这就是将东西打印到控制台的本质。所有东西、标准输出、标准错误等都会被假脱机打印到控制台上,但是由于java本身是多线程的,所以无法保证这些项目被添加到队列中以进行打印。
多线程可以做一些有趣的事情!
https://stackoverflow.com/questions/31267907
复制相似问题