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 强制输出或者 缓存满, 那么 缓存大小 默认是多少呢? 默认是 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);