摘选自网络文件
在java程序中,性能问题的大部分原因并不在于java语言,而是程序本身。养成良好的编码习惯非常重要,能够显著地提升程序性能。
1,尽量在合适的场合使用单例
使用单例可以减轻加载的负担,缩短加载的时间,提升加载的效率,但不是所有地方都使用于单例,简单来说,单例主要使用于以下三个方面。
a.控制资源的使用,通过线程同步来控制资源的并发访问
b.控制实例的产生,以达到节约资源的目的
c.控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信
单例模式的使用-->java面试篇之手写静态内部类实现单例
2.尽量避免随意使用静态变量
当某个对象被定义为static变量所引用,那么GC通常是不会回收这个对象所占用的内存。
public class A{
private static B b=new B();
}
此时静态变量b的生命周期与A同步,如果A类不会卸载,那么b对象会常驻内存,直至程序终止。
标注一下:个人理解尽量将实例对象不定义为类变量,这个场景很少用到。
3.尽量避免过多过常地创建java对象
尽量避免在经常调用的方法,循环中new对象,由于系统不仅需要花时间来创建对象,而且还要花时间对这些对象进行垃圾回收和处理,最大限度地重用对象,最好能用基本的数据类型和数组来代替对象。
标注一下:new对象基本上是放入在堆内存空间
4.尽量使用局部变量
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中,速度较快,其它变量如静态变量,实例变量等都在堆中创建,速度较慢。
6.尽量处理好包装类型和基本类型两者的使用场所
虽然包装类型和基本类型在使用过程中可以相互转换,但他们两者所产生的内存区域是完全不同的,基本类型数据产生和处理都在栈中处理,包装类型是对象,是在堆中产生实例。在集合类对象,有对象方法需要的处理使用包装类型,其它的处理提倡使用基本类型。
7.慎用synchronized,尽量减小synchronized的方法范围
都知道,实现同步是需要很大的系统开销作为代价的,甚至可能造成死锁。所以尽量避免无谓的同步控制。synchronized方法被调用时,直接会被当前对象或者当前类锁了,在方法执行完之前其它线程无法调用当前对象,当前类的被锁住的方法,所以synchronized的方法尽量减小,并且应尽量使用同步代码块代替同步方法。
8.尽量使用基本数据类型代替对象
String str="hello",上面这种方式会创建一个"hello"字符串,而且jvm的字符缓冲池还会缓存这个字符串;String str=new String("hello"),此时程序除创建字符串外,str所引用的String对象底层还包含一个char[]数组,这个char[]数组依次存放了h,e,l,l,o。
9.多线程在未发生线程安全前提下应尽量使用HashMap,ArrayList
HashTable,Vector等使用了同步机制,降低了性能。
10.尽量合理的创建HashMap
当你要创建一个比较大的hashMap时,充分利用这个构造函数
public HaashMap(int initialCapacity,float loadFactor);
避免HashMap多次进行了hash重构扩容是一件很耗费性能的事,在默认中initialCapacity只有16,而loadFactor是0.75,需要多大的容量,你最好能准确的估计你所需要的最佳大小,同样的HashTable,Vector也是一样的道理。
11.尽量减少对变量的重复计算
for(int i=0;i<list.size();i++)
可替换为以下方面
for(int i=0,len=list.size();i<len;i++)
并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快
12.尽量避免不必要的创建
A a=new A();
if(i==1){
List list=new List();
list.add(a);
}
应该更改为以下方式
if(i==1){
List list=new List();
A a=new A();
list.add(a);
}
13.尽量在finally块中释放资源
程序中使用到的资源应当被释放,以避免资源泄露,这最好在finally块中去做,不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。
14.尽量使用移位运算符代替/符号进行乘除的操作
"/"是一个代价很高的操作,使用移位的操作将会更快和更有效,如
int num=a/4; int num=a/8;可以使用int num=a>>2;int num=a>>3;
int num=a*4; int num=a*8;可以使用int num=a<<2;int num=a<<3;
需要注意的是使用移位操作符应该添加注释,因为移位操作不直观,比较难理解。
15.尽量确定StringBuffer的容量
StringBuffer的构造器会创建一个默认大小,通常是16的字符数组,在使用中,如果超出这个大小,就会重新分配大小,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提交性能。