Java代码优化

系统性能优化通常分为下面几步走:java

一、发现问题数据库

    这一步须要先进行一些性能测试,根据测试结果找出不达标的来进一步分析优化。好比:B/S系统能够在浏览器上安装一些插件(我用的是httpwatch),打开浏览器后进入系统,启动插件的功能,点击查询按钮,该插件就会自动记录查询整个过程的耗时,能够方便你后面的分析,下图为httpwatch某个查询的耗时记录:编程

    根据性能测试结果要写一份性能测试报告为下一步工做提供依据,写性能测试报告通常有如下几点须要写进去:数组

         a、测试使用数据是否为现场数据浏览器

         b、测试使用的客户端是什么配置安全

         c、服务器数据库端的配置性能优化

         d、选择的测试条件服务器

         e、每一个功能测试次数,平均耗时为多少dom

         f、每次查询返回的数据量函数

         g、数据库里对应表里的数据总量

         h、将测试记录写成文档,对于不达标的记录高亮显示

二、分析问题

    根据测试报告找出不达标的功能进行单独分析,肯定存在问题的具体位置,好比是某个方法仍是某个功能段致使总体性能不能达标,通常会先大概分析一下总体的代码,而后从外向里添加日志,打印出各方法的执行时间,这样很快就能肯定出问题的具体位置,将分析结果写入文档,为下一步提供依据。

三、提出方案

    根据分析结果提出解决方案,而后写成文档提交审批。

四、解决问题

    根据审批经过的文档进行修改,而后测试修改后的结果,符合要求了就能够提交测试部进行最总测试。

五、结果报告

    测试部测试经过后一个优化就算结束了,写好优化文档上传保存。

 

    上面的这几步每一步都很重要,可是真正难点仍是在第三步,提出解决方案,代码优化、逻辑优化甚至是数据库的优化都须要有丰富的编程经验,这个不是一会儿能作到的须要长期的积累,在项目里不断的实践才可以越作越好,下面我就将一些看到过的优化方法结合本身的工做总结出来以供参考:

 

 

java代码优化

一、循环

一般把大循环放在里面,把小循环放在外面,例如:

for(int i=0; i<10;i++) {  
    for(int j=0; j<1000000;j++)  {   
            ...  
    }  
}

把与循环index不相关的移到循环的外面,例如:

for(int i=0; terminal=x.length;i<terminal;i++)  {
    x = x/scaleA * scaleB;
}  
//应该该成:  
Double scale = scaleB*scaleA;  
for(int i=0; terminal=x.length;i<terminal;i++)  {
    x = x/scale ;
}

在重要的循环里,消除循环终止判断时的方法调用,例如:

for(int i=0; i<collection.size();i++)  { 
    ... 
}  
//尽可能减小对变量的重复计算  
for(int i=0; n=collection.size();i<n;i++)  {
    ...
}

尽可能不要在循环中使用:

Try {  
} catch() {  
}

应把其放置在最外层

循环内不要建立大量的临时变量

for(int i=1;i<=domainCount;i++){  
        ...   
       AuditResult auditResult = new AuditResult();  
        ...  
}  
//这种作法会在内存中保存N份这个对象的引用,会浪费大量的内存空间,改成  
AuditResult auditResult;  
for(int i=1;i<=domainCount;i++){  
        ...   
       auditResult=new AuditResult();  
        ...  
}

二、字符串

     ■ 消除字符串链接

  ■建立长字符串时,老是使用StringBuffter代替String

  ■预先分配StringBuffer空间 StringBuffer sb = new StringBuffer(5000);

    ■ StringBuffer 和StringBuilder的区别:

    java.lang.StringBuffer线程安全的可变字符序列。一个相似于String 的字符串缓冲区,但不能修改。

    StringBuilder,与该类相比,一般应该优先使用java.lang.StringBuilder类,由于它支持全部相同的操做,但因为它不执行同步,因此速度更快。

三、异常

         ■ 异常只用于单个真正的错误条件,抛出一个异常和执行一个catch代码块花费是很高的(主要因为当建立一个异常时要得到线程栈的一个快照),只当条件真的异常时才抛出一个异常

  ■ 抛出异常首先要建立一个新的对象。

  Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。

  只要有异常被抛出,JVM就必须调整调用堆栈,由于在处理过程当中建立了一个新的对象。

  异常只能用于错误处理,不该该用来控制程序流程。

  ■使编译器和运行时最优化,将几个方法调用放在一个try/catch块中,而不是为每一个方法调用实现几个try/catch块,例如:

try{   
    Some.method1(); //Difficut for java1.4   
}catch(method1Exception e){   
    handle exception 1 // to optimize this code   
}  
try{   
    Some.method2(); //Difficut for java1.4   
}catch(method2Exception e){   
    handle exception 2 // to optimize this code   
}  
try{   
    Some.method3(); //Difficut for java1.4   
}catch(method3Exception e){   
    handle exception 3 // to optimize this code   
}  
//应该写为:  
try{   
    //Difficut for java1.4   
    Some.method1();   
    Some.method2();   
    Some.method3();   
}catch(method1Exception e){   
    handle exception 1   
}catch(method2Exception e){   
    handle exception 2   
}catch(method3Exception e){   
    handle exception 3   
}

四、尽可能指定类的final修饰符

          ■带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String。其为String类指定final也防止了人们覆盖length()方法。

  另外,若是指定一个类为final,则该类全部的方法都是final。Java编译器会寻找机会内联(inline)全部的final方法(这和具体的编译器实现有关)。此举可以使性能平均提升50%。

五、尽可能使用局部变量

          ■调用方法时传递的参数以及在调用中建立的临时变量都保存在栈(Stack)中,速度较快。其余变量,如静态变量、实例变量等,都在堆(Heap)中建立,速度较慢。另外,依赖于具体的编译器/JVM,局部变量还可能获得进一步优化

六、乘法和除法

for (val = 0; val < 100000; val +=5) {   
    alterX = val * 8;   
    myResult = val * 2;  
}  
//优化后:  
for (val = 0; val < 100000; val += 5) {   
    alterX = val << 3;   
    myResult = val << 1;  
}

这个还须要看具体状况,并非全部的乘除法都能这样优化。

七、array(数组) 和 ArrayList的使用

    array([]):最高效;可是其容量固定且没法动态改变;

    ArrayList:容量可动态增加;但牺牲效率;

    基于效率和类型检验,应尽量使用array,没法肯定数组大小时才使用ArrayList。

    ArrayList内部封装了一个Object类型的数组,从通常的意义来讲,它和数组没有本质的差异,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。

八、在JAVA + ORACLE的应用系统开发中,java中内嵌的SQL语句尽可能使用大写的形式,以减轻ORACLE解析器的解析负担

九、因为JVM的有其自身的GC机制,不须要程序开发者的过多考虑,从必定程度上减轻了开发者负担,但同时也遗漏了隐患,过度的建立对象会消耗系统的大量内存,严重时会致使内存泄露,所以,保证过时对象的及时回收具备重要意义。JVM回收垃圾的条件是:对象不在被引用;然而,JVM的GC并不是十分的机智,即便对象知足了垃圾回收的条件也不必定会被当即回收。因此,建议咱们在对象使用完毕,应手动置成null,这样也能够提供性能。

十、尽可能采用lazy loading 的策略

即在须要的时候才开始建立,例如:

String str = “aaa”;   
if(i == 1) {  
    list.add(str);   
}  
//应替换为:  
if(i == 1) {  
    String str = “aaa”;   
    list.add(str);   
}

十一、在使用同步机制时,应尽可能使用方法同步代替代码块同步

12、当复制大量数据时,使用System.arraycopy()命令

相关文章
相关标签/搜索