字符串链接效率测试:stringbuilder》stringbuffer》+ 【转:尽可能使用StringBuilder和StringBuffer进行字符串链接】

前几天性能测试的时候发现一个web 端cpu出现骤降的问题,一直没有找到缘由,起初怀疑是tomcat的线程数有关,后来有怀疑是跟数据库的响应时间太长有关系,后来都一一排除了。 java

之因此此问题比较难以定位主要是由于经过现有的监控工具没法获知和分析tomcat内部各个线程的占用资源的状况。 web

上周装了一下jprofiler,而后又从新进行了一次压力测试,终于找到了问题的根源:) 数据库

主要的资源消耗点是:字符串的拼接上。代码中时使用”+“来进行字符串链接的。 tomcat

(ps:jprofiler监控的粒度很细,可是因为其自己运行占用的资源消耗量也很大,所以在进行性能测时不能用其做为监控工具,在分析问题方面仍是蛮有用的;jconsole是java自带的监控工具,其在远程监控应用程序时,不会对程序的性能形成影响,但因为其监控的粒度仍是有些粗,所以tomcat内部的资源占用状况仍是没法进行分析的 安全

 

 

JAVA中String ,StringBuffer,SrtingBuilder三个对象链接字符串的效率。
比较下究竟谁的效率高。由于咱们常常都听有经验的人说,避免使用String经过“+”链接字符串,特
别是链接的次数不少的时候,必定要用StringBuffer,但究竟效率多高,速度多快,我也没有测试过,
因此我就动手测试下,顺便把测试结果跟你们一块儿分享,但愿你们共同讨论此问题。
下边是个人测试代码,可直接运行:
app

 

public class TestStringConnection {
    
    //链接时间的设定
    private final static int n = 20000;
    
    public static void main(String[] args){
       TestStringConnection test = new TestStringConnection ();
       test.testStringTime(n);
       test.testStringBufferTime(n);
       test.testStringBuilderTime(n);
       
       
//       //链接10次
//       test.testStringTime(10);
//       test.testStringBufferTime(10);
//       test.testStringBuilderTime(10);
//       
//       //链接100
//       
//       test.testStringTime(100);
//       test.testStringBufferTime(100);
//       test.testStringBuilderTime(100);
//       
//       
//       
//       //链接1000
//       
//       test.testStringTime(1000);
//       test.testStringBufferTime(1000);
//       test.testStringBuilderTime(1000);
//       
//       
//      //链接5000
//       
//       test.testStringTime(5000);
//       test.testStringBufferTime(5000);
//       test.testStringBuilderTime(5000);
//       
//       
// //链接10000
//       
//       test.testStringTime(10000);
//       test.testStringBufferTime(10000);
//       test.testStringBuilderTime(10000);
//       
// //链接20000
//       
//       test.testStringTime(20000);
//       test.testStringBufferTime(20000);
//       test.testStringBuilderTime(20000);
    }
    
    /**
     *测试String链接字符串的时间
     */
    public void testStringTime(int n){
       long start = System.currentTimeMillis();
       String a = "";
       for(int k=0;k<n;k++ ){
           a += "_" + k;
       }
       long end = System.currentTimeMillis();
       long time = end - start;
       System.out.println("//////////////////////链接"+n+"次" );
       System.out.println("String time "+n +":"+ time);
       //System.out.println("String str:" + str);
    }
    
    /**
     *测试StringBuffer链接字符串的时间
     */
    public void testStringBufferTime(int n){
       long start = System.currentTimeMillis();
       StringBuffer b = new StringBuffer() ;
       for(int k=0;k<n;k++ ){
           b.append( "_" + k );
       }
       long end = System.currentTimeMillis();
       long time = end - start;
       System.out.println("StringBuffer time "+n +":"+ time);
       //System.out.println("StringBuffer str:" + str);
    }
    
    /**
     *测试StringBuilder链接字符串的时间
     */
    public void testStringBuilderTime(int n){
       long start = System.currentTimeMillis();
       StringBuilder c = new StringBuilder() ;
       for(int k=0;k<n;k++ ){
           c.append( "_" + k );
       }
       long end = System.currentTimeMillis();
       long time = end - start;
       System.out.println("StringBuilder time " +n +":"+ time);
       
       System.out.println("//////////////////////");
       //System.out.println("StringBuffer str:" + str);
    }

}
 

 

分别测试了n=10,100,500,1000,5000,10000,20000的时候,三个对象链接字符串所花费的时间,
作了个简单统计,获得以下数据:

 

测试环境:eclipse

由上边的图表结果对比,能够清楚的看出,为何你们都鼓励用StringBuffer链接字符串了。在链接次数少
的状况下,String的低效率表现并非很突出,可是一旦链接次数多的时候,性能影响是很大的,String进
行2万次字符串的链接,大约须要1分钟时间,而StringBuffer只须要94毫秒,相差接近500倍以上。而
StringBuffer和StringBuilder差异并不大,StringBuilder比StringBuffer稍微快点,我想是由于StringBuffer
是线程序安全的,StringBuilder不是线程序安全的,因此StringBuffer稍微慢点。

可是为何String如此慢呢,分下以下简单片断 String result="";
result+="ok"; 这段代码看上去好像没有什么问题,可是须要指出的是其性能很低,缘由是java中的String 类不可变的(immutable),这段代码实际的工做过程会是如何的呢?经过使用javap工具我 们能够知道其实上面的代码在编译成字节码的时候等同的源代码是: String result="";

StringBuffer temp=new StringBuffer();
temp.append(result);
temp.append("ok");
result=temp.toString();
短短的两个语句怎么呢变成这么多呢?问题的缘由就在String类的不可变性上,而java程序为了方便简单的
字符串使用方式对+操做符进行了重载,而这个重载的处理可能所以误导不少对java中String的使用。
因此,若是你对字符串中的内容常常进行操做,特别是内容要修改时,那么使用StringBuffer,若是最后 须要String,那么使用StringBuffer的toString()方法好了。可是 StringBuilder 的实例用于多个线程是不安 全的。若是须要这样的同步,则建议使用 StringBuffer,由于StringBuffer是线程安全的。在大多数非多 线程的开发中,为了提升效率,能够采用StringBuilder代替StringBuffer,速度更快。
相关文章
相关标签/搜索