JDK源码系列:StringBuffer与StringBuilder对比

48c65eaaae397fdce6c162d514556b0d.jpeg

一、源码分析StringBuffer与StringBuilder的区别

1、StringBuffer是多线程安全的,StringBuilder是多线程不安全的

多线程安全指的是 多个线程同时对一个对象进行append 等操作,不会出现覆盖、丢失的情况。

看下StringBuffer是如何做到多线程安全的:

fbe4cc9c06d83548d6dac23d734e2bf1.png

StringBuffer类中除了构造方法,几乎所有方法都加了synchronized关键字来保证线程安全。

相对来说StringBuilder就要任性的多:

231d6d0edefcb6e341269b48938c9608.png

2、性能问题「JDK1.8」

理论上 不加锁的方法肯定比加锁的方法要快,但在单线程场景下 应该说是两者差距不大了,因为 synchronized 在高版本jdk里经过了偏向锁的优化,性能接近单线程了。

但是toString方法要注意了,在单线程场景下多次调用toString方法,StringBuffer性能更高,因为它使用了缓存,而StringBilder没有使用缓存

3、内存占用问题

在多次调用toString 方法场景下,StringBuffer占用内存更少,因为使用了字符数组缓存共享,而StringBuilder没有使用缓存共享

4、toString()实现原理对比

这个方法最终是要调用的,看看有啥区别

1)StringBuffer实现

a6c498c9e17b0a43a688c7335a7eac66.png

由源码可以看出,不管调用多少次toString 方法,始终只会在第一次进行一次字符数组复制,之后就是共享,内存不会有大的变化(String对象是新的,但是内容一直在共享)

2)StringBuilder实现

e127686dfa2693f6b60ac58712d403a2.png

由源码可以看出,每调一次toString 方法,都会进行字符数组复制,产生一个崭新的String对象。在某些场景下可能出现内存占用问题。

二、实际使用中注意事项

由源码分析可知,对于较大的字符串拼接场景,toString方法使用不当,内存占用峰值会有很大差异

1、对StringBuffer而言toString()调用时机不同,内存峰值持续时间会有较大差异

假设需要一个方法来拼接一个大的字符串:

实现方式1:

6953fb45a4ddc3c963e62bcf28e60802.png

实现方式2:

653eda087a805cdd72e64c6b83e1de15.png

仔细体会这两种写法,思考内存变化情况

2、对StringBuilder而言toString()重复调用问题,如果不及时释放,内存占用会持续升高

对StringBuilder而言,除了1中提到的问题,还有一个内存不断升高问题

63f6299172bc6309d53bdabd278134df.png

关注吕哥,关注代码质量

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吕哥架构

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值