StringBuilder的toString⽅法
前⼏天发布应⽤出现了点问题,排查过程中同事发在⾥⼀篇⽂章,仔细看了⼀下,还是挺有意思的,于是⾃⼰模拟了⼀下场景,
原⽂在这⾥,⼀次简单致命的错误:
在频繁的进⾏字符串的操作增加的时候,我们会优先考虑使⽤StringBuilder和StringBuffer,其中StringBuffer是线程安全的。有个⼩地⽅需要慎重,就是toString()⽅法。
先看这段代码://读取⽂件,然后在⽂件的末尾追加⼀些特殊字符然后换⾏
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(
new FileReader("E:\\java_tools\\hatrix1.28\\hatrix.log"));
StringBuilder sb = new StringBuilder();java的tostring方法
String str = null;
while((adLine())!=null){
if(StringUtils.String())){
sb.append("$$$$$$$$\r");
}
sb.append(str);
}
System.out.String());
}
上⾯标红的这⾥,在⼩应⽤或者数据量不⼤的情况下完全没有问题,但是在数据量⼤,并且并发多的时候,就会出现问题。
在Stringbuilder的代码中看toString()的代码如下
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
每次调⽤toString⽅法,会重新new⼀个String出来。
在java.lang.String的代码中,看最后⼀⾏,value并不是直接指向的,⽽是通过系统拷贝函数进⾏的内存操作
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.offset = 0;
this.value = pyOfRange(value, offset, offset+count);
}
java.util.Arrays中关于数组拷贝
public static char[] copyOfRange(char[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
char[] copy = new char[newLength];
System.arraycopy(original, from, copy, 0,  Math.min(original.length - from, newLength));
return copy;
}
那为啥会通过内存拷贝的形式来进⾏toString呢,原因在于StringBuilder内部有两个核⼼的属性,这两个记录了String中的内容,是字符数组的形式。
这时候对于字符数组操作,通过内存拷贝是最快的⽅式了。
/**
* The value is used for character storage.
*/
char value[];
/**
* The count is the number of characters used.
*/
int count;
上述代码中,CPU会⼀直忙于进⾏内存的分配⼯作,会导致机器的load过⾼
解决办法:
⽤StringBuilder类中的length来判断是否有数值,这样就避免了⽆谓的内存操作。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。