【问题标题】:Race between System.out and System.err in java [duplicate]java中System.out和System.err之间的竞争[重复]
【发布时间】:2013-02-15 08:07:28
【问题描述】:

请考虑这个java代码:

public class CMain {
    public static void main(String[] args){

        for (int i = 0; i < 10; i++) {
            System.out.println("A");
            System.err.println("B");
        }

    }
}

快速浏览一下代码,我们中的一些人可能会认为输出必须是 As 和 Bs 的输出。但事实并非如此!随机出现10个A字和10个B字。像这样的:

这是为什么呢?以及解决方案是什么,以便交替显示 As 和 Bs ( A B A B A B ...) 在我问这个问题之前,我检查了其他几个类似的问题以寻求解决方案,但不适用于我的案例!我带了一些来这里:

【问题讨论】:

  • 这是两个不同的流,碰巧合并到同一个控制台中。如果您希望所有内容都按给定顺序放在一个地方,为什么不使用单个流(out OR err)?
  • 我认为答案在您的第二个链接中“问题是终端仿真器(在您的情况下为 Eclipse)负责处理应用程序的标准输出和标准错误。没有与终端仿真器通信时,您永远无法确定 out 和 err 以正确的顺序显示。因此,我会考虑在 err 上打印所有内容并将其重定向到文件。您仍然可以使用 out 进行干净的用户交互。"
  • 两个流是同步的,但不是在同一个锁上,所以你应该期待一些交错......但是,每个流都将单独排序。
  • @owlstead 基本上说:设计。 ;-)

标签: java synchronization system.out system.err


【解决方案1】:
Why does this happen?

这是因为out 和err 是两个不同的输出流。但是,它们都在控制台上打印。因此,您不会将它们视为不同的流。此外,当您执行out.println() 时,不能保证您会在执行语句后立即在控制台上看到输出。相反,字符串通常(取决于系统)存储在输出缓冲区中(如果您愿意的话),稍后由系统处理以将缓冲区的输出放到屏幕上。

Solution :(

虽然,正如 Eng.Fouad 指出的那样,您可以使用 setOut(System.err) 或 setErr(System.out) 对它们进行排序,但我仍然不建议您在实际将其放入应用程序时这样做(仅用于调试目的)。

建议的解决方案的作用是最终将只使用一个流作为标准输出和标准错误,我认为这不是一件好事。

【讨论】:

  • 我猜这取决于系统,Ankit...
  • @owlstead 是的(我假设你在谈论缓冲)
【解决方案2】:

它们是不同的OutputStreams。如果您确实需要保证打印顺序,请使用:

System.setErr(System.out);

或

System.setOut(System.err);

【讨论】:

  • 这可能会起作用,但您会失去 Eclipse 应用的突出显示。
  • @owlstead 这和替换 System.err.println("B"); 是一样的。与 System.out.println("B");
  • @Cgraphics 是的,几乎一样。这就像对同一个流有 2 个引用。
  • @Cgraphics 当然,但是(临时)更改 System.out 或 System.err 以便能够在 Eclipse 中正确调试和更改每个 System.out.println 语句之间存在差异...
【解决方案3】:

由于有两个单独的流,因此您提供的输出是可能的。

【讨论】:

  • 取决于系统,System.out 和 System.err 默认是自动刷新的。 eclipse 没有检测到字节或字符的写入顺序。它们必须按顺序排列,因为 println() 应该只在 刷新流之后返回。
  • 你是对的,我完全同意你的看法。这就是为什么 A/B 的顺序是可能的。也可以有任何订单。
猜你喜欢
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-17
  • 1970-01-01
  • 2016-02-02
  • 2013-11-14
相关资源
最近更新 更多