博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
有助于改善性能的技巧
阅读量:6324 次
发布时间:2019-06-22

本文共 3607 字,大约阅读时间需要 12 分钟。

1. 慎用异常

  在Java软件开发中,经常会使用try-catch进行错误捕获,但是,try-catch语句对系统性能而言是非常糟糕的。因此,应尽量避免将其应用在循环当中。

2. 使用局部变量

  调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其它变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。

3. 位运算代替乘除法

  在所有的运算中,位运算是最为高效的。因此,可以尝试使用位运算代替部分算术运算,来提高系统的运算速度。最典型的就是对于整数的乘除法运算优化。

4. 替换switch

  关键字switch语句用于多条件判断,switch语句的功能类似于if-else语句,两者的性能也差不多。因此,不能说switch语句会降低系统的性能。但是,在绝大部分情况下,switch语句还是有性能提升空间的。

  来看下面的例子:

int re = 0;        for(int i=0;i<10000000;i++){            re = switchInt(i);        }        protected int switchInt(int z){            int i = z%10 + 1;            switch(i){                case 1:return 3;                case 2:return 6;                case 3:return 7;                case 4:return 8;                case 5:return 10;                case 6:return 16;                case 7:return 18;                case 8:return 44;                default:return -1;            }        }

  上例中,就分支逻辑而言,这种switch模式的性能并不差。但是如果换一种全新的思路替代switch,实现相同的程序功能,那么性能就能有很大的提升空间。以下代码实现了与上例switch语句相同的功能:

int re = 0;        int[] sw = new int[]{0, 3, 6, 7, 8, 10, 16, 18, 44}; //替代switch逻辑        for(int i=0;i<10000000;i++){            re = arrayInt(sw, i);        }        protected int arrayInt(int[] sw, int z){            int i = z%10 + 1;            if(i<1||i>8)    //模拟switch的default                return -1;            else                return sw[i];        }

  以上代码采用全新的思路,使用一个连续的数组代替了switch语句。因为对数组的随机访问时非常快的,至少好于switch的分值判断,因此它的速度一定会快于原来的实现。通过实验,使用switch的语句相对耗时80ms,而使用数组的实现只相对耗时62ms。

5. 一维数组代替二维数组

  由于数组的随机访问性能非常好,许多JDK类库,如Arraylist、Vector等都使用了数组作为其底层实现。但是,作为软件开发人员也必须知道,一维数组和二维数组的访问速度是不一样的。一维数组的访问速度要优于二维数组。因此,在性能敏感的系统中要使用二维数组的,可以尝试通过可靠的算法,将二维数组转为一维数组再进行处理,以提高系统的响应速度。

6. 提取表达式

   在软件开发过程中,程序员很容易有意无意地让代码做一些“重复劳动”,在大部分情况下,由于计算机的高速运行,这些“重复劳动”并不会对性能构成太大的威胁,但若希望将系统性能发挥到极致,提取这些“重复劳动”相当有意义。尽可能让程序少做重复计算,尤其要关注在循环体内的代码,从循环体内提取重复的代码可以有效地提升系统性能。

7. 展开循环

   与前面所介绍的优化技巧略有不同,展开循环是一种在极端情况下使用的优化手段,因为展开循环很可能会影响代码的可读性和可维护性,而这两者对软件系统来说也是极为重要的。但是,当性能问题成为系统的主要矛盾时,展开循环绝对是一种值得尝试的技术。

一个普通的循环代码如下所示:

     int[] array = new int[9999999];        for(int i=0;i<9999999;i++){            array[i] = i;        }

展开循环后,类似以下格式:

int[] array = new int[9999999];        for(int i=0;i<9999999;i += 3){            array[i] = i;            array[i+1] = i+1;            array[i+2] = i+2;        }

  以上两段代码功能完全相同,但第二段代码进行了循环展开的优化,在一个循环体内处理了原代码段中的3个循环逻辑。运行以上两段代码,第一段代码相对耗时94ms,第二段代码相对耗时31ms,可见展开循环后,减少循环次数,对提升系统性能很有帮助。

8. 布尔运算代替位运算

   虽然位运算的速度远远高于算术运算,但是在条件判断时,使用位运算替代布尔运算却是非常错误的选择。因为在条件判断时,Java会对布尔运算做相当充分的优化。在布尔表达式的计算中,只要表达式的值可以确定,就会立即返回,而跳过剩余子表达式的计算。若使用位运算(按位与、按位或)代替逻辑与和逻辑或,虽然位运算本身性能没有问题,但是位运算总是要将所有的子表达式全部计算完成后,再给出最终结果。因此,从这个角度说,使用位运算替代布尔运算会使系统进行很多无用计算。

9. 使用arraycopy()

  数组复制是一项使用频率很高的功能,JDK中提供了一个高效的API来实现它:

public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

  System.arraycopy()函数是native函数,通常native函数的性能要优于普通函数,仅出于性能考虑,在软件开发时,应尽可能调用native函数。

10. 使用Buffer进行I/O操作

  除NIO外,使用java进行I/O操作有两种基本方式:

  1. 使用基于InputStream和OutputStream的方式
  2. 使用Writer和Reader

  无论使用哪种方式进行文件的I/O,如果能合理地使用缓冲,就能有效地提高I/O的性能。

 11. 使用clone()代替new

  在Java中新建对象实例最常用的方法是使用new关键字。JDK对new关键字的支持非常好,使用new关键字创建轻量级对象时,速度非常快。但是,对于重量级对象,由于对象在构造函数中可能会进行一些复杂而且耗时的操作,因此,构造函数的执行时间可能会比较长。这就导致了创建对象的耗时很长,同时也使得系统无法在短期内获得大量的实例。为了解决这个问题,可以使用Object.clone()方法。

  Object.clone()方法可以绕过对象构造函数,快速复制一个对象实例。由于不需要调用对象构造函数,因此,clone()方法不会受到构造函数性能的影响,能够快速生成一个实例。但是,在默认的情况下,clone()方法生成的实例只是原对象的浅拷贝。如果需要深拷贝,则需要重新实现clone()方法。

 12. 静态方法替代实例方法

  使用关键字static声明的方法为静态方法。在Java中,由于实例方法需要维护一张类似虚函数表的结构,以实现对多态的支持。与静态方法相比,实例方法的调用需要更多的资源。因此,对于一些常用的工具类方法,没有对其进行重载的必要,那么就可以将它们声明为static,便可以加速方法的调用。对于一些工具类,应该使用static方法实现,这样不仅可以加速函数调用的速度,同时,调用static方法也不需要生成类的实例,比调用实例方法更为方便、易用。

 

转载地址:http://xxlaa.baihongyu.com/

你可能感兴趣的文章
8.3折抢购最欢迎的Mac清理工具CleanMyMac3
查看>>
第十五章 springboot + pojo默认值设置
查看>>
linux grep命令
查看>>
Button MouseEvent颜色变化
查看>>
django自身提供的sitemap和feed实现样例
查看>>
Entity Framework Code First (一)Conventions
查看>>
强制使用栅格图
查看>>
P1045 麦森数
查看>>
数据结构习题之多维数组和广义表
查看>>
C# 多线程详解 Part.03 (定时器)
查看>>
register_globals使用详解
查看>>
iOS:iOS开发系列–打造自己的“美图秀秀”(上)
查看>>
数据库连接未关闭,conn与rs未关闭
查看>>
Primes on Interval(二分 + 素数打表)
查看>>
用同一个工程创建两个不同版本的应用
查看>>
js 四舍五入函数 toFixed(),小数位数精度
查看>>
zabbix 监控java程序
查看>>
【USACO 2.4】Cow Tours (最短路)
查看>>
openfire源码修改后如何打包部署到linux服务器上
查看>>
form表单提交和阻止
查看>>