慎用System.out.println!!!

初学者一般在开发中或者调试bug的时候,都会习惯性的使用System.out.println语句,输出到控制台中,观察数据是否正常。开发或者调试完毕,很可能就忘记删除,直接就发布到生产中去了。

image

问题导入

有童鞋会说,那有啥关系的,不就是控制台多打印一些日志嘛。那今天老师就和童鞋们分析一下,System.out.println输出语句对服务性能的影响。

场景设置

假如你的服务对性能要求极高,不能容忍请求响应时间过长,这个时候你的代码就不应该含有System.out.println语句,为什么这么说呢?下面看一下,老师给童鞋们做的一个小测试,代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
long start1 = System.currentTimeMillis();
for(int i=0;i<100000;i++){
System.out.println("i:"+i);
}
long end1 = System.currentTimeMillis();
System.out.println("有输出语句的耗时:"+(end1-start1));
long start2 = System.currentTimeMillis();
for(int i=0;i<100000;i++){
}
long end2 = System.currentTimeMillis();
System.out.println("无输出语句的耗时:"+(end2-start2));
}

有输出语句的耗时:408
无输出语句的耗时:0

从打印结果我们可以看到,循环10w次的打印时间需要耗时408毫秒,没有打印的循环几乎等于0毫秒。

原理分析

那这个时候问题就来了,为什么System.out.println语句会这么耗费性能呢?不要着急,我们看一下System.out.println语句的源码就知道答案了。

1
2
3
4
5
6
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}

从System.out.println的源代码,我们可以看到它在一开始就用synchronized同步锁给锁起来了,所以System.out.println是一个同步方法,在高并发的情况下,会严重影响性能。

总结

在日常开发或者调试的过程中,尽量使用log4j2或者logback这些异步的方法,进行日志的统一收集,禁止使用System.out.println。项目上线前也要进行全局搜索,防止有人误提交带有System.out.println的代码。

后记

其实写文章的时候,老师还有一点小问题没有给出解答,童鞋们可以自己思考一下。

  1. System.out.println会输出到tomcat容器的catalina.out文件中吗?
  2. System.out.println在error级别的日志中,会输出日志吗?
  3. System.out.println在IDEA中的快捷键符号是啥?
林老师带你学编程 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!