StringBuilder与StringBuffer
一个线程不安全一个线程安全.但StringBuilder效率更高.
如何高性能场景下使用StringBuilder
首先,我们得了解StringBuilder存在的两个问题,线程不安全以及char[]重复扩容的影响.
new StringBuilder() 时char[]的默认长度是16,然后,如果要append第17个字符,怎么办?用System.arraycopy成倍复制扩容!这样一来有数组拷贝的成本,二来原来的char[]也白白浪费了要被GC掉。可以想见,一个129字符长度的字符串,经过了16,32,64, 128四次的复制和丢弃,合共申请了496字符的数组,在高性能场景下,这几乎不能忍。
如何解决(参考jdk的BigDecimal类)
BigDecimal里面有这么两段代码
1.通过ThreadLocal封装StringBuilderHelper
private static final ThreadLocal<StringBuilderHelper>
threadLocalStringBuilderHelper = new ThreadLocal<StringBuilderHelper>() {
@Override
protected StringBuilderHelper initialValue() {
return new StringBuilderHelper();
}
};
2.StringBuilderHelper的主要定义
static class StringBuilderHelper {
final StringBuilder sb; // Placeholder for BigDecimal string
final char[] cmpCharArray; // character array to place the intCompact
StringBuilderHelper() {
sb = new StringBuilder();
// All non negative longs can be made to fit into 19 character array.
cmpCharArray = new char[19];
}
// Accessors.
StringBuilder getStringBuilder() {
sb.setLength(0);
return sb;
}
}
ThreadLocal的使用解决了StringBuilder的并发不安全问题.
StringBuilder.setLength()函数重置它的count指针,而char[]则会继续重用,而toString()时会把当前的count指针也作为参数传给String的构造函数,所以不用担心把超过新内容大小的旧内容也传进去了。
cmpCharArray = new char[19]指定大小,包含最大long值.
网友评论