前几天发布应用出现了点问题,排查过程中同事发在群里一篇文章,仔细看了一下,还是挺有意思的,于是自己模拟了一下场景,
原文在这里,一次简单致命的错误:http://www.blogjava.net/xylz/archive/2012/03/15/371966.html
在频繁的进行字符串的操作增加的时候,我们会优先考虑使用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();
String str = null;
while((str=reader.readLine())!=null){
if(StringUtils.isNotEmpty(sb.toString())){
sb.append("$$$$$$$$\r");
}
sb.append(str);
}
System.out.println(sb.toString());
}
上面标红的这里,在小应用或者数据量不大的情况下完全没有问题,但是在数据量大,并且并发多的时候,就会出现问题。
在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.count = count;
this.value = Arrays.copyOfRange(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来判断是否有数值,这样就避免了无谓的内存操作。
分享到:
相关推荐
主要生成StringBuilder 字符串 类似 StringBuilder builder = new StringBuilder(); builder.AppendFormat("<span class=\"navSep\"></span>\r\n"); builder.AppendFormat("机构看盘</a>\r\n"); builder....
自动生成如下格式的SQL语句;很方便哦! StringBuilder sb=new StringBuilder(); sb.Append("SELECT * FROM Table \n"); sb.Append("WHERE A="B" \n"); return sb.ToString();
一、StringBuffer和StringBuilder的区别是什么? Java中的StringBuffer和StringBuilder类是用于处理字符串的可变对象;...String str = sb.toString(); System.out.println(str); // 输出: Hello World // 在指定位置
简介区别 String的缺点是每次字符串变量的内容发生了改变时,都必须重新分配内存...执行完之后,将调用ToString方法把工作区中的内容转换为一个字符串,方便赋给一个字符串变量。这样StringBuilder会提升一些性能。 St
字符串生成器javascript StringBuilder 将选择一种快速的方式来运行字符串连接。 单元测试 var sb = new StringBuilder ( ) ; sb . append ( "a" ) . append ( "b" ) ; sb . appends ( "a" , "b" ) ; console . log ...
所有的append方法都是泛型的( Append(T value) )并直接写入缓冲区而不是连接value.ToString T1 〜 T16 AppendFormat( AppendFormat(string format, T1 arg1, ..., T16 arg16)避免拳击的结构参数 也T1 〜 T16的...
对字符串进行操作的方法实际上返回的是新的字符串 对象。因此,出于性能方面的原因,大量的连接或其他涉及字符串的操作应当用 StringBuilder 类执行,如下所示: System.Text.StringBuilder sb = new System.Text....
在C#中,在处理字符串拼接的时候,使用StringBuilder的效率会比硬拼接字符串高很多。到底有多高,如下: static void Main( string[] args ) { string str1 = string.Empty; Stopwatch sw1 = new Stopwatch(); ...
String和StringBuilder和StringBuffer,这三个都是值得深究一翻的,可能很多人会说,实在不行的话,都全部用StringBuilder,啥...所以建议使用(在把值类型转换为字符串的时候,记得用ToString方法)。所以平时写代码的时
1.1 toString方法 1.2 equals方法 1.3 String类中的equals方法与Object类中的equals方法的不同点 1.4 StringBuilder类与String类的区别 2. 时间日期类 2.1 Date类 2.2 DateFormat类 2.3 Calendar类 3. System类 ...
StringBuilder sb = new StringBuilder(sts.szVendorInfo, 200); sb.AppendFormat(" ver:{0}.{1}.{2}", sts.wMajorVersion, sts.wMinorVersion, sts.wBuildNumber); txtStatus.Text = sb.ToString(); // set ...
String dx = new StringBuilder(need).append(LL).append(userId).toString(); int suf = this.decode(dx); String code = new StringBuilder(need).append(String.valueOf(suf)) .toString(); return ...
1、使用值类型的ToString方法 在连接字符串时,经常使用”+”号直接将数字添加到字符串中。这种方法虽然简单,也可以得到正确结果,但是由于涉及到不同的数据类型,数字需要通过装箱操作转化为引用类型才可以添加到...
StringBuilder sql = new StringBuilder(string.Format(@" select * from BS_Template t where 1=1 ")); if (!string.IsNullOrWhiteSpace(noticeType)) { sql.AppendFormat(" and nt.name like '%{0}%'", ...
4.12 实验12 ToString()方法的使用 298 4.12.1 实验目标 298 4.12.2 实验步骤 298 4.13 实验13 将字符串转化为其他类型 300 4.13.1 实验目标 300 4.13.2 实验步骤 300 4.14 实验14 Regex类的使用 302 4.14.1 实验...
StringBuilder sb = new StringBuilder(); for (int i = 0; i ; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString(); } catch (Exception ex) { throw new Exception("GetMD5...
return (num.ToString() + "." + num2.ToString() + "." + num3.ToString() + "." + num4.ToString()); } public IpLocation Query(string ip) { IpLocation ipLocation = new IpLocation(); if(string....
本文实例讲述了C#实现将汉字转化为2位大写的16进制Unicode的方法。分享给大家供大家参考。具体实现方法如下: 说明: str.ToString(“x”) : 转为1位16进制小写 ...var sb =new StringBuilder(); if (string.
Label1.Text = dt.ToString();//2005-11-5 13:21:25 Label2.Text = dt.ToFileTime().ToString();//127756416859912816 Label3.Text = dt.ToFileTimeUtc().ToString();//127756704859912816 Label4.Text = dt....
static extern bool InternetGetCookieEx(string pchUrl, string pchCookieName, StringBuilder pchCookieData, ref System.UInt32 pcchCookieData, int dwFlags, IntPtr lpReserved); private static string ...