面试官:关于Java性能优化,你有什么技巧

经过使用一些辅助性工具来找到程序中的瓶颈,而后就能够对瓶颈部分的代码进行优化。java

通常有两种方案:即优化代码或更改设计方法。咱们通常会选择后者,由于不去调用如下代码要比调用一些优化的代码更能提升程序的性能。而一个设计良好的程序可以精简代码,从而提升性能。程序员

下面将提供一些在JAVA程序的设计和编码中,为了可以提升JAVA程序的性能,而常常采用的一些方法和技巧。数据库

1.对象的生成和大小的调整。缓存

JAVA程序设计中一个广泛的问题就是没有好好的利用JAVA语言自己提供的函数,从而经常会生成大量的对象(或实例)。因为系统不只要花时间生成对象,之后可能还需花时间对这些对象进行垃圾回收和处理。所以,生成过多的对象将会给程序的性能带来很大的影响。安全

例1:关于String ,StringBuffer,+和append网络

JAVA语言提供了对于String类型变量的操做。但若是使用不当,会给程序的性能带来影响。架构

以下面的语句:并发

file

  1. 看似已经很精简了,其实并不是如此。为了生成二进制的代码,要进行以下的步骤和操做:
    file

由此能够看出,这两行简单的代码,就生成了STR1,STR2,STR3,STR4和STRBUF1五个对象变量。这些生成的类的实例通常都存放在堆中。app

堆要对全部类的超类,类的实例进行初始化,同时还要调用类及其每一个超类的构架器。而这些操做都是很是消耗系统资源的。所以,对对象的生成进行限制,是彻底有必要的。函数

经修改,上面的代码能够用以下的代码来替换。

file

系统将进行以下的操做:

file

由此能够看出,通过改进后的代码只生成了四个对象变量:STR1,STR2,STR3和STRBUF_1.你可能以为少生成一个对象不会对程序的性能有很大的提升。

但下面的代码段2的执行速度将是代码段1的2倍。由于代码段1生成了八个对象,而代码段2只生成了四个对象。

代码段1:

file

代码段2:

file

所以,充分的利用JAVA提供的库函数来优化程序,对提升JAVA程序的性能时很是重要的.其注意点主要有以下几方面;

一、尽量的使用静态变量(Static Class Variables)

若是类中的变量不会随他的实例而变化,就能够定义为静态变量,从而使他全部的实例都共享这个变量。

例:

file

就能够定义为:

file

二、不要对已生成的对象做过多的改变。

对于一些类(如:String类)来说,宁愿在从新生成一个新的对象实例,而不该该修改已经生成的对象实例。

例:

file

上述代码生成了三个String类型的对象实例。而前两个立刻就须要系统进行垃圾回收处理。若是要对字符串进行链接的操做,性能将得更差,由于系统将不得为今生成更多的临时变量,如上例1所示。

三、生成对象时,要分配给它合理的空间和大小JAVA中的不少类都有它的默认的空间分配大小。

对于StringBuffer类来说,默认的分配空间大小是16个字符。若是在程序中使用StringBuffer的空间大小不是16个字符,那么就必须进行正确的初始化。

四、避免生成不太使用或生命周期短的对象或变量。

对于这种状况,应该定义一个对象缓冲池。觉得管理一个对象缓冲池的开销要比频繁的生成和回收对象的开销小的多。

五、只在对象做用范围内进行初始化。

JAVA容许在代码的任何地方定义和初始化对象。这样,就能够只在对象做用的范围内进行初始化。从而节约系统的开销。

例:

file

能够修改成:

file

2.异常(Exceptions)

JAVA语言中提供了try/catch来发方便用户捕捉异常,进行异常的处理。可是若是使用不当,也会给JAVA程序的性能带来影响。

所以,要注意如下两点:

一、避免对应用程序的逻辑使用try/catch

若是能够用if,while等逻辑语句来处理,那么就尽量的不用try/catch语句。

二、重用异常

在必需要进行异常的处理时,要尽量的重用已经存在的异常对象。觉得在异常的处理中,生成一个异常对象要消耗掉大部分的时间。

  1. 线程(Threading)

一个高性能的应用程序中通常都会用到线程。由于线程能充分利用系统的资源。在其余线程由于等待硬盘或网络读写时,程序能继续处理和运行。可是对线程运用不当,也会影响程序的性能。

例2:正确使用Vector类

Vector主要用来保存各类类型的对象(包括相同类型和不一样类型的对象)。可是在一些状况下使用会给程序带来性能上的影响。这主要是由Vector类的两个特色所决定的。

第一,Vector提供了线程的安全保护功能。即便Vector类中的许多方法同步。可是若是你已经确认你的应用程序是单线程,这些方法的同步就彻底没必要要了。

第二,在Vector查找存储的各类对象时,经常要花不少的时间进行类型的匹配。而当这些对象都是同一类型时,这些匹配就彻底没必要要了。

所以,有必要设计一个单线程的,保存特定类型对象的类或集合来替代Vector类。用来替换的程序以下(StringVector.java):

file

所以,代码:

file

能够用以下的代码替换:

file

这样就能够经过优化线程来提升JAVA程序的性能。

用于测试的程序以下(TestCollection.java):

file

关于线程的操做,要注意以下几个方面:一、防止过多的同步

如上所示,没必要要的同步经常会形成程序性能的降低。所以,若是程序是单线程,则必定不要使用同步。

二、同步方法而不要同步整个代码段

对某个方法或函数进行同步比对整个代码段进行同步的性能要好。

三、对每一个对象使用多”锁”的机制来增大并发。

通常每一个对象都只有一个”锁”,这就代表若是两个线程执行一个对象的两个不一样的同步方法时,会发生”死锁”。即便这两个方法并不共享任何资源。为了不这个问题,能够对一个对象实行”多锁”的机制。

以下所示:

file

4.输入和输出(I/O)

输入和输出包括不少方面,但涉及最多的是对硬盘,网络或数据库的读写操做。对于读写操做,又分为有缓存和没有缓存的;对于数据库的操做,又能够有多种类型的JDBC驱动器能够选择。但不管怎样,都会给程序的性能带来影响。

所以,须要注意以下几点:

一、使用输入输出缓冲

尽量的多使用缓存。但若是要常常对缓存进行刷新(flush),则建议不要使用缓存。

二、输出流(Output Stream)和Unicode字符串

当使用Output Stream和Unicode字符串时,Write类的开销比较大。由于它要实现Unicode到字节(byte)的转换.所以,若是可能的话,在使用Write类以前就实现转换或用OutputStream类代替Writer类来使用。

三、当需序列化时使用transient

当序列化一个类或对象时,对于那些原子类型(atomic)或能够重建的原素要表示为transient类型。这样就不用每一次都进行序列化。若是这些序列化的对象要在网络上传输,这一小小的改变对性能会有很大的提升。

四、使用高速缓存(Cache)

对于那些常常要使用而又不大变化的对象或数据,能够把它存储在高速缓存中。这样就能够提升访问的速度。这一点对于从数据库中返回的结果集尤为重要。

五、使用速度快的JDBC驱动器(Driver)

JAVA对访问数据库提供了四种方法。这其中有两种是JDBC驱动器。一种是用JAVA外包的本地驱动器;另外一种是彻底的JAVA驱动器。具体要使用哪种得根据JAVA布署的环境和应用程序自己来定。

  1. 一些其余的经验和技巧

file

小编最近将收集的Java程序员进阶架构师的资料作了一些整理,免费分享给每一位学习Java的朋友。须要的能够进群:751827870

————————————end————————————
> 本文由博客一文多发平台 [OpenWrite](https://openwrite.cn?from=article_bottom) 发布! 复制代码
相关文章
相关标签/搜索