Java String—String, StringBuilder, StringBuffer

1.简介

字符串相关类型主要有这三种:String、StringBuffer、StringBuilder,其中 StringBuffer、StringBuilder 都是可以变的字符串类型,StringBuffer 在字符串拼接时使用 synchronized 来保障线程安全,如图:
在这里插入图片描述
因此在多线程字符串拼接中推荐使用 StringBuffer。StringBuilder 的使用方法和 StringBuffer 一样,它们都继承于 AbstractStringBuilder。
性能:String 每次修改相当于生成一个新对象,因此性能最低;StringBuffer 使用 synchronized 来保证线程安全,性能优于 String,但不如 StringBuilder;

2.StringBuilder线程安全问题

StringBuilder为什么线程不安全?
对比一下StringBuilder与StringBuffer的区别:
在这里插入图片描述
在这里插入图片描述
多线程情况下StringBuilder线程安全问题

StringBuilder stringBuilder = new StringBuilder();
        for(int i =0; i<10; i++){
            new Thread( () -> {
                for(int j = 0; j<1000; j++){
                    stringBuilder.append("a");
                }
            }).start();
        }
        Thread.sleep(100);
        System.out.println(stringBuilder.length());

在这里插入图片描述
每次运行,stringBuilder.length() 数值几乎都小于预期结果:10000,期间还会出现数组越界的异常。
原因分析:
进入SringBuilder append 方法,发现调用super.append(), 进入此方法,
在这里插入图片描述
扩容的逻辑就是:new一个新的char数组,新的char数组的容量是原来char数组的两倍再加2,再通过System.arryCopy()函数将原数组的内容复制到新数组,最后将指针指向新的char数组。
在这里插入图片描述
在这里插入图片描述
拷贝流程:
在这里插入图片描述
假设现在有两个线程同时执行了StringBuilder的append()方法,两个线程都执行完了第五行的ensureCapacityInternal()方法,此刻count=5.
在这里插入图片描述
这个时候线程1的cpu时间片用完了,线程2继续执行。线程2执行完整个append()方法后count变成6了。线程1继续执行第六行的str.getChars()方法的时候拿到的count值就是6了,执行char数组拷贝的时候就会抛出ArrayIndexOutOfBoundsException异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值