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 强制输出或者 缓存满, 那么 缓存大小 默认是多少呢? 默认是 8kb。因为 底层都是 BufferedWriter

System.out 和 System.err 的区别

 

 

 

 

 

另外,测试发现,

第一批 是先打印  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);

 

PrintWriter write 没有输出,(8192 没有输出, 8193 才有输出)

        char[] array = new char[8192];// 8192 没有输出, 8193 才有输出
        Arrays.fill(array,'s');
        PrintWriter pw= new PrintWriter(System.out);
        pw.write(array);// 8192 没有输出, 8193 才有输出

 

但是呢, 似乎也不能累加,第一次如果设置 数组小于 8193, 后面再write 也没有用!

        char[] array = new char[8192];
        Arrays.fill(array,'s');
        PrintWriter pw= new PrintWriter(System.out);
        pw.write(array);// 8192 没有输出, 8193 才有输出

        char[] array2 = new char[7190];
        Arrays.fill(array2,'c');
        pw.write(array2);

 

这样才可以():

char[] array = new char[8192];
        Arrays.fill(array,'s');
        PrintWriter pw= new PrintWriter(System.out);
        pw.write(array);// 8192 没有输出, 8193 才有输出

        char[] array2 = new char[7190];
        Arrays.fill(array2,'c');
        pw.write(array2);

        array2 = new char[1];
        Arrays.fill(array2,'c');
        pw.write(array2);

        array2 = new char[1000];
        Arrays.fill(array2,'c');
        pw.write(array2);

        array2 = new char[3];
        Arrays.fill(array2,'c');
        pw.write(array2);

此时要大于 两个 8192 才可以! 至于为什么,我也没有深究。 感觉怪怪的。

 

另外就是发现,flush 方法的话,会及时刷出,不会有不输出的问题。PrintWriter(OutputStream out, boolean autoFlush) 的autoFlush参数, 也无助于上面的问题,而是仅仅对  println, printf, or format 方法起作用; 它会在执行 println, printf, or format 方法的时候,会 flush the output buffer。

 

相关文章: