java对于类型有歧义_日志输出都有歧义!字符拼接 VS 占位符,到底该采用哪种方式?...

前言

说来也巧,这几天正在看一本书,叫做《Java系统性能优化实战》,李家智著的,在代码审查这章中提到了一个关于日志输出问题,先看一下我们原本是怎么输出信息的,如下。

private static  Logger logger = LoggerFactory.getLogger(FileManageApplication.class);

public static void main(String[] args){

logger.info("日志输出{}",1);

}

第一个参数是格式化模板,“{}”是占位符,第二个参数是类型可以是Object... arguments的,会将第一个参数中的"{}"依次替换为这个数组中的数据,不出意外的话,会输出如下信息。

2021年01月07日 19:52:09:INFO main (FileManageApplication.java:35) - 日志输出1

但是他却不建议使用这种方式,理由是日志框架内部会有一个把占位符"{}"替换成目标变量的耗时过程,考虑到info方法可能被频繁调用,对性能有影响,所以建议直接拼接,代码如下:

public static void main(String[] args){

User user  =getUser();

logger.info("用户名:"+user.getUserName());

}

这听起来似乎也有几分道理,但是在今天早上刷到了一篇公众号文章,里面也恰好提到了这个问题(是个某大V),里面这样说:“不要进行字符串拼接,那样会产生很多String对象,占用空间,影响性能”。

what???

68bfdf3476ef0c6acd06a67b23f67ce1.gif

并且他给出了一个反例,如下:

logger.debug("Processing trade with id: " + id + " symbol: " + symbol);

并且还有个正例,如下:

logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol)

另外这样的格式,可读性更好,对于排查问题更有帮助。

所以,最后我们用什么方法?

下面我们还是自己看测试一下把。

时间比较

使用拼接方式

public class Main{

private static Logger logger = LoggerFactory.getLogger(Main.class);

public static void main(String[] args){

long startTimer = System.currentTimeMillis();

for (int i = 0; i 

logger.info("i="+i);

}

System.out.println(System.currentTimeMillis()-startTimer);

}

}

运行10次,结果是如下,平均是512.2。

534、510、486、518、495、505、526、507、511、530

使用模板方式

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

public class Main{

private static Logger logger = LoggerFactory.getLogger(Main.class);

public static void main(String[] args){

long startTimer = System.currentTimeMillis();

for (int i = 0; i 

logger.info("i={}",i);

}

System.out.println(System.currentTimeMillis()-startTimer);

}

}

运行10次,结果是如下,平均是642.9。

654、648、599、624、678、660、643、656、583、684

确实如书中所说,替换"{}"的过程比较耗时。

这里没使用System.out.println()做比较,因为他实在太慢了,因为内部会涉及到加锁。

内存占用比较

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import javax.swing.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

public class Main extends JFrame{

private static Logger logger = LoggerFactory.getLogger(Main.class);

public Main(){

this.setSize(300, 300);

this.setVisible(true);

this.setDefaultCloseOperation(EXIT_ON_CLOSE);

JButton jButton = new JButton("开始");

jButton.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e){

for (int i = 0; i 

logger.info("i={}",i);

//                    logger.info("i="+ i);

}

}

});

this.add(jButton);

}

public static void main(String[] args){

new Main();

}

}

模板方式

点击按钮等待输出完成后,内存停留在112,764KB。

68bfdf3476ef0c6acd06a67b23f67ce1.gif

执行GC后降到13,484KB。

68bfdf3476ef0c6acd06a67b23f67ce1.gif

拼接方式

点击按钮等待输出完成后,内存停留在128,014KB,相差15,250KB。

68bfdf3476ef0c6acd06a67b23f67ce1.gif

执行GC后降到17,777KB。

68bfdf3476ef0c6acd06a67b23f67ce1.gif

在这次比较中,拼接方式占用的内存较高,也符合公众号中所说。

结论

显然都各胜一筹,所以只能看看自己需求了,另外在如Tomcat源码中,使用的也是拼接方式....

还有在阿里巴巴Java开发手册中这样说....

68bfdf3476ef0c6acd06a67b23f67ce1.gif

- END -

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值