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 的打印結果有不同的顏色

估計是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 :

 

 

可以看到, 對於 test System.err = xx 打印, xx 都是遞增的, 單獨是有序的,但是System.out 、 System.err整體就不是了!

 

 

 

把 1000 改成2000, 看到了不同的結果, 看來是 println 方法有緩存, 觀察源碼發現,這個緩存是 java io底層實現的sun  io 的緩存。

 

 

當print 流緩存未滿的時候, println不會立即輸出, 而是等待 一個flush 強制輸出或者 緩存滿, 那么 緩存大小 默認是多少呢? 默認是 8kb。因為 底層都是 BufferedWriter

 

 

 

 

 

另外,測試發現,

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM