java

位置:IT落伍者 >> java >> 浏览文章

进阶教程——Java性能优化通用篇


发布日期:2022年04月22日
 
进阶教程——Java性能优化通用篇

通用篇

通用篇讨论的问题适合于大多数Java应用

不用new关键词创建类的实例

用new关键词创建类的实例时构造函数链中的所有构造函数都会被自动调用但如果一个对象实现了Cloneable接口我们可以调用它的clone()方法clone()方法不会调用任何类构造函数

在使用设计模式(Design Pattern)的场合如果用Factory模式创建对象则改用clone()方法创建新的对象实例非常简单例如下面是Factory模式的一个典型实现

public static Credit getNewCredit() {return new Credit();}

改进后的代码使用clone()方法如下所示

private static Credit BaseCredit = new Credit();public static Credit getNewCredit() {return (Credit) BaseCreditclone();}

上面的思路对于数组处理同样很有用

使用非阻塞I/O

版本较低的JDK不支持非阻塞I/O API为避免I/O阻塞一些应用采用了创建大量线程的办法(在较好的情况下会使用一个缓沖池)这种技术可以在许多必须支持并发I/O流的应用中见到如Web服务器报价和拍卖应用等然而创建Java线程需要相当可观的开销

JDK 引入了非阻塞的I/O库(javanio)如果应用要求使用版本较早的JDK在这里有一个支持非阻塞I/O的软件包

慎用异常

异常对性能不利抛出异常首先要创建一个新的对象Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法fillInStackTrace()方法检查堆栈收集调用跟蹤信息只要有异常被抛出VM就必须调整调用堆栈因为在处理过程中创建了一个新的对象

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

不要重复初始化变量

默认情况下调用类的构造函数时 Java会把变量初始化成确定的值所有的对象被设置成null整数变量(byteshortintlong)设置成float和double变量设置成逻辑值设置成false当一个类从另一个类派生时这一点尤其应该注意因为用new关键词创建一个对象时构造函数链中的所有构造函数都会被自动调用

尽量指定类的final修饰符

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

另外如果指定一个类为final则该类所有的方法都是finalJava编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)此举能够使性能平均提高%

尽量使用局部变量

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

乘法和除法

考虑下面的代码

for (val = ; val < 100000; val +=5) { alterX = val * 8; myResult = val * 2; }

用移位操作替代乘法操作可以极大地提高性能。Tw.WIngwiT.com下面是修改后的代码:

for (val = 0; val < 100000; val += 5) { alterX = val << 3; myResult = val << 1; }

修改后的代码不再做乘以8的操作,而是改用等价的左移3位操作,每左移1位相当于乘以2。相应地,右移1位操作相当于除以2。值得一提的是,虽然移位操作速度快,但可能使代码比较难于理解,所以最好加上一些注释。

上一篇:全面挖掘Java Excel API 使用方法

下一篇:Java中的枚举器(反复器)