【java】关于StringBuffer和StringBuilder的理解
程序员文章站
2022-06-01 11:53:22
...
应用
StringBuffer和StringBuilder都可以用来构建字符串,与String类一样,内部都维护一个char数组,但是String类里的char数组是使用final
关键字修饰的,所以不可变。
区别
StringBuffer是线程安全的,StringBuilder是线程不安全的,StringBuffer的操作使用synchronized
关键字加锁,从而保证了多线程情况下的线程安全。
StringBuilder线程不安全的样例
/**
* @author 阳光大男孩!!!
*/
public class StringbuilderTest {
public static void main(String[] args) throws InterruptedException {
StringBuilder stringBuilder = new StringBuilder();
int cnt=0;
for(int i=0;i<10;i++)
{
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<1000;j++)
{
stringBuilder.append("a");
}
}
}).start();
}
Thread.sleep(1000);
System.out.println(stringBuilder.length());
}
}
执行结果是9997
,明显这是一个错误的数据。当然不一定是9997,因为多线程的结果不是必现的,即不可预测的。
首先,StringBuilder类继承自AbstractStringBuilder
类,AbstractStringBuilder
类有两个我们需要注意的变量,分别是字符数组value
和字符数组的使用情况count
.
这个继承就很关键,StringBuilder也就拥有从父类-AbstractStringBuilder
类继承过来的数据结构.当我们上面示例代码中多线程去调用StringBuilder的append
方法时,会使用super
关键字去执行父类也就是AbstractStringBuilder
类的append
方法
继续看父类的append
方法
第一行进行了判空操作,第四行确保数组的长度够用,第五行的作用则在于将新加进来的字符串加到value
字符数组中。
导致我们上面示例程序错误的是count+=len
这一步,这一步并非原子操作,当多线程同时执行这个方法的时候,就会导致数据错误的问题。
总结
在单线程的环境下,可使用StringBuilder,而在多线程,例如网络编程的情况下还是要用StringBuffer的。