System.out 和 System.err 的区别

System.out 和 System.err 的区别, 很基础吧,

 

但是 仔细观察idea 的后台日志, 你会有新的发现。

 

测试一段极其简单的代码:

public class TestBasic {
 
    public static void main(String[] args) {
        System.out.println("test System.out = " + 111);
        System.err.println("test System.err = " + 222);
        System.out.println("test System.out = " + 111);
        System.err.println("test System.err = " + 222);
        System.out.println("test System.out = " + 111);
        System.err.println("test System.err = " + 222);
    }

}

 

结果:

System.out 和 System.err 的区别

 

 

第一个问题:为什么System.out 和 System.err 的打印结果有不同的颜色

估计是idea 的控制台的默认的 人性化的设置 —— 使用cmd 命令行, 肯定的、自然不会有红色。 linux shell 呢? 

 

第二个问题: 为什么是先白后红, 而不是红白相间的呢? 跟我的程序的操作的顺序不一样啊! why ?!

 

不够快吗? 线程切换吗? 打印更多试试:

public class TestBasic {
 
    public static void main(String[] args) {
        System.out.println("test System.out = " + 111);
        System.err.println("test System.err = " + 222);
        System.out.println("test System.out = " + 111);
        System.err.println("test System.err = " + 222);
        System.out.println("test System.out = " + 111);
        System.err.println("test System.err = " + 222);

        for (int i = 0; i < 1000; i++) {
            System.out.println("test System.out = " + i);
            System.err.println("test System.err = " + i);
        }
    }

}

 

还是一样的的, 显示白色的System.out, 再是红色的 System.err :

System.out 和 System.err 的区别

 

 

可以看到, 对于 test System.err = xx 打印, xx 都是递增的, 单独是有序的,但是System.out 、 System.err整体就不是了!

 

 

 

把 1000 改成2000, 看到了不同的结果, 看来是 println 方法有缓存, 观察源码发现,这个缓存是 java io底层实现的sun  io 的缓存。

System.out 和 System.err 的区别

 

 

当print 流缓存未满的时候, println不会立即输出, 而是等待 一个flush 强制输出或者 缓存满, 那么 缓存大小 默认是多少呢? 默认是 4kb。

 

 

另外,测试发现,

第一批 是先打印  System.out 还是 System.err , 和 第一行有关, 上面的测试代码, 如果把第一行和第二行调换一下, 那么 打印的结果是 先红后白了!

 

本质上还是同步的, 没有异步的问题。 之前 一直在想, 是不是 异步线程导致了这个问题?

 

另外, 

 

java.lang.Throwable#printStackTrace()  其实是使用的是 System.err :

    public void printStackTrace() {
        printStackTrace(System.err);
    }

    /**
     * Prints this throwable and its backtrace to the specified print stream.
     *
     * @param s {@code PrintStream} to use for output
     */
    public void printStackTrace(PrintStream s) {
        printStackTrace(new WrappedPrintStream(s));
    }

    private void printStackTrace(PrintStreamOrWriter s) {
        // Guard against malicious overrides of Throwable.equals by
        // using a Set with identity equality semantics.
        Set<Throwable> dejaVu =
            Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
        dejaVu.add(this);

        synchronized (s.lock()) {

    ...

 

当然, 我们可以改变, 比如:

throwables.printStackTrace(System.out);

 

System.out 和 System.err 的区别

上一篇:8.28 校内模拟赛 题解报告


下一篇:GC面试重点:垃圾回收机制