StringBuilder和StringBuffer的区别
基本概念
StringBuilder/StringBuffer 字符串变量
- 详细点就是:
* 没有final修饰
* 相对于String来讲是变量,而String是 final 修饰的常量;
*
* 就是个弟弟
* StringBuilder 开始出现于JDK 5,最早出现在 C# 中;
*
* 没安全感,容易翻车
* StringBuilder:非线程安全的可变字符序列;
*
* “闪电”(树懒)般的安全感
* StringBuffer: 线程安全的可变字符序列;
主要区别
1.线程安全与否
StringBuilder 非线程安全 / StringBuffer 线程安全
相对于什么安全呢? 当然是在操作字符序列时候。上源码
StingBuilder
StringBuffer
在synchronized修饰下即加锁,多个线程访问时,只有一个线程获锁,其余线程等待,直到上一线程释放锁;StringBuffer 在多线程情况下保证了在操作时的原子性,使得被操作字符序列是安全的。
- 但是 为什么没有synchronized修饰会出现多线程下操作不安全呢?继续看源码
StringBuilder
StringBuilder继承了AbstractStringBuilder,其append等方法调用的是父类的append方法,方法中出现了 “+=” 的操作,这就是它的弱点
假如:- 线程A 调用append方法,count 做一次 + 操作,未返回结果
- 此时,线程B同样调用,count 做一次 + 操作,返回结果
- 接着线程A 开始返回结果
-
那么它得到的是 本身加一次 和 线程B加一次的count值,出现数据的脏读。
所以说,在没有锁的保证下,多线程情况时,容易出现操作后数据不准确问题。
小结:StringBuilder就是个弟弟(JDK 5出现),比较皮(非线程安全)
2.操作效率高低
- StringBuilder 执行效率高于 StringBuffer
- 为什么?
- 简单: StringBuilder 未加锁,没有线程切换的时间开销
顺带说一下String
- string 是 final修饰的字符串常量,在操作改变字符序列长度、内容时,实际是使用了新的对象完成的。看图:
- 效率,肯定是低于 上面两者的
我们通过简单的查看 HashCode 值的方式可以判断 String 和 StringBuilder 二者在操作字符串序列式,使用的对象了; - String 使用了新的对象去处理拼接操作;需要内存及时间消耗,比StringBuilder慢;
- StringBuilder 在操作时,仍然是原有对象,内存占用低于String,自然效率高;
小结:
- 不涉及 字符串长度及内容相对大量变化时,正常使用 String 即可满足需求;
- 不涉及 多线程操作字符串序列时,正常选用 StringBuilder 即可满足需求,且效率较高;
- 当程序中涉及大量线程是,乖乖的用 StringBuffer,量大需要,小心它闹
- 安全 StringBuilder < StringBuffer
- 效率 StringBuilder > StringBuffer