【java】关于StringBuffer和StringBuilder的理解

喜欢ヅ旅行 2023-07-05 11:48 37阅读 0赞

前言

事实上,我们在开发中,比较常用的字符串拼接方式是“+=”,而这种方式在JDK1.5以后就默认是使用String类的append()方法。

使用append()方法损耗大,而StringBuilder 为动态数组可以有效的降低字符串拼接的损耗。

应用

StringBuffer和StringBuilder都可以用来构建字符串,与String类一样,内部都维护一个char数组,但是String类里的char数组是使用final关键字修饰的,所以不可变。
在这里插入图片描述

区别

StringBuffer是线程安全的,StringBuilder是线程不安全的,StringBuffer的操作使用synchronized关键字加锁,从而保证了多线程情况下的线程安全。

StringBuilder线程不安全的样例

  1. /**
  2. * @author 阳光大男孩!!!
  3. */
  4. public class StringbuilderTest {
  5. public static void main(String[] args) throws InterruptedException {
  6. StringBuilder stringBuilder = new StringBuilder();
  7. int cnt=0;
  8. for(int i=0;i<10;i++)
  9. {
  10. new Thread(new Runnable() {
  11. @Override
  12. public void run() {
  13. for(int j=0;j<1000;j++)
  14. {
  15. stringBuilder.append("a");
  16. }
  17. }
  18. }).start();
  19. }
  20. Thread.sleep(1000);
  21. System.out.println(stringBuilder.length());
  22. }
  23. }

执行结果是9997,明显这是一个错误的数据。当然不一定是9997,因为多线程的结果不是必现的,即不可预测的。

首先,StringBuilder类继承自AbstractStringBuilder类,AbstractStringBuilder类有两个我们需要注意的变量,分别是字符数组value和字符数组的使用情况count.
在这里插入图片描述

这个继承就很关键,StringBuilder也就拥有从父类-AbstractStringBuilder类继承过来的数据结构.当我们上面示例代码中多线程去调用StringBuilder的append方法时,会使用super关键字去执行父类也就是AbstractStringBuilder类的append方法
在这里插入图片描述
继续看父类的append方法
在这里插入图片描述
第一行进行了判空操作,第四行确保数组的长度够用,第五行的作用则在于将新加进来的字符串加到value字符数组中。
在这里插入图片描述
导致我们上面示例程序错误的是count+=len这一步,这一步并非原子操作,当多线程同时执行这个方法的时候,就会导致数据错误的问题。

既然StringBuffer是线程安全的,为什么还要用StringBuilder?

在单线程下,是可以用StringBuilder的,因为它的性能比StringBuffer是要高的。

总结

在单线程的环境下,可使用StringBuilder,而在多线程,例如网络编程的情况下还是要用StringBuffer的。

发表评论

表情:
评论列表 (有 0 条评论,37人围观)

还没有评论,来说两句吧...

相关阅读