StringBuffer和StringBuilder都是继承了抽象类AbstractStringBuilder
为什么说StringBuilder不是线程安全的,而StringBuffer是线程安全的呢?
我们去看看源码就知道了.
先看
StringBuilder的构造方法
public StringBuilder append(String str) { super.append(str); return this; }
这里的super的append方法就是AbstractStringBuilder抽象类的方法
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; }
1.这里的count是一个共享变量,对共享变量做+=操作是可能出现问题的,
count += len;
这不是一个原子操作,可能在多线程的时候出现问题.
2.拷贝数据
private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) {//如果要插入的字符和以前的已有的字符串的和大于现在的长度,那么就要执行copy了,把value拷贝的新的数组容器中 value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } }
private int newCapacity(int minCapacity) { // overflow-conscious code int newCapacity = (value.length << 1) + 2;//扩容2的一次方倍+2,就是x*2+2 if (newCapacity - minCapacity < 0) {//如果计算后的长度小于要扩容的长度,那就直接用着长度 newCapacity = minCapacity; } return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)//如果newCapacity小于等于0,或者newCapacity比MAX_ARRAY_SIZE还大的话就返回字符实际的长度,否则返回计算后的长度newCapacity ? hugeCapacity(minCapacity) : newCapacity; }
private int hugeCapacity(int minCapacity) { if (Integer.MAX_VALUE - minCapacity < 0) { // overflow throw new OutOfMemoryError(); } return (minCapacity > MAX_ARRAY_SIZE) ? minCapacity : MAX_ARRAY_SIZE; }
是否比最大值大,如果大返回自己,否则返回最大值
StringBuffer为什么是线程安全的,因为他有synchronized
public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; }
所以他是线程安全的,但是效率比StringBuilder低一些