StringBuilder和StringBuffer都继承自AbstractStringBuilder类,StringBuffer是线程安全的,StringBuilder是线程不安全的。StringBuilder相对于StringBuffer速度更快。
StringBuilder为什么线程不安全?
StringBuilder类的append()方法:
image.png
StringBuilder的append()方法重写了父类AbstractStringBuilder类的append()方法,并且方法内部调用了父类的append()方法。
AbstractStringBuilder类的append()方法:
image.png
问题就在于append()方法内调用的ensureCapacityInternal(count + len)方法,count为AbstractStringBuilder的成员变量,len是追加字符串的长度。AbstractStringBuilder有两个成员变量:
image.png
value是一个字符数组,用于存储组成字符串的字符,count表示字符数组中已存储的字符数。在创建StringBuilder或StringBuffer类的对象时会初始化value的容量,默认是16。
image.png
image.png
image.png
image.png
image.png
image.png
若追加的字符串长度加上count(字符数组中已用字符数量)大于value的长度,则需要对value继续扩容,扩容的实质是创建一个新的更大容量的数组,并将原来数组中的元素复制到新的数组当中。
判断容量是否够用,不够用就要扩容:
image.png
扩容的规则为原来数组的长度的两倍再加2,若还是不够,则直接返回count与追加字符串长度的和:
image.png
在多线程的环境下,若两个线程同时进行append操作,count与追加字符串的和刚好等于value数组的长度,通过ensureCapacityInternal方法判断无需扩容,若其中一个线程先进行了追加操作,另外一个线程则不能再进行追加操作。
那么StringBuffer是如何保证线程安全的呢?
image.png
因为StringBuffer类在重写这些方法时都使用了synchronized。
网友评论