【109期】面试官:我们说StringBuilder是线程不安全的,是什么原因呢?
阅读本文大概需要 3.4 分钟。
来自:juejin.im/post/5d6228046fb9a06add4e37fe
引言
分析
public class StringBuilderDemo {
public static void main(String[] args) throws InterruptedException {
StringBuilder stringBuilder = new StringBuilder();
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(100);
System.out.println(stringBuilder.length());
}
}
1、为什么输出值跟预期值不一样
//存储字符串的具体内容
char[] value;
//已经使用的字符数组的数量
int count;
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
2、为什么会抛出ArrayIndexOutOfBoundsException异常。
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
void expandCapacity(int minimumCapacity) {
//计算新的容量
int newCapacity = value.length * 2 + 2;
//中间省略了一些检查逻辑
...
value = Arrays.copyOf(value, newCapacity);
}
public static char[] copyOf(char[] original, int newLength) {
char[] copy = new char[newLength];
//拷贝数组
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
str.getChars(0, len, value, count);
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
//中间省略了一些检查
...
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
推荐阅读:
【108期】面试官:你真的知道 Java 类是如何被加载的吗?
【107期】谈谈面试必问的Java内存区域(运行时数据区域)和内存模型(JMM)
【106期】面试官:Java中的finally一定会被执行吗?
微信扫描二维码,关注我的公众号
朕已阅
评论