J2EE系统优化的几点体会
当前位置:以往代写 > JAVA 教程 >J2EE系统优化的几点体会
2019-06-14

J2EE系统优化的几点体会

J2EE系统优化的几点体会

副标题#e#

J2EE系统优化的几点体会(一、工具)

说到系统优化,是一个较量巨大的问题,涉及到软件的各个方面:需求、模块分别、数据库设计、措施编码以及一些非凡的优化要领如缓存技能等。而差异的应用又有其非凡的优化计策和技能。同时优化是贯串系统从需求到实现再到维护的各个阶段的一项勾当,而在各个阶段又有其差异的着眼点和详细要领。

本文驻足于详细的J2EE项目实践,团结一些已有的优化条例,提出本身的一些体会,也算是作为一次对实际项目履历教导的总结。

优化一般意义上说是提高已有系统的机能,淘汰如内存、数据库、网络带宽等资源的占用,是在系统开拓告一段落的前提下举办。一般是通过压力测试或详细利用发明机能方面的问题,然后寻找机能瓶颈,并团结项目进度、人员布置、技能储蓄等因素,提出相应的优化计策。

下面团结一些案例,举办详细的接头,并但愿能总结出一些具有代表性的条例:

条例一:只管重用工具,制止建设过多短时工具

工具在面向工具编程中到处可见,甚至可以绝不浮夸的说是:“一切都是工具”。如何更好的建设和利用工具,是优化中要思量的一个重要方面。笔者将工具按利用分为两大类:独享工具和共享工具。独享工具指由某个线程单独拥有并维护其生命周期的工具,一般是通过new 建设的工具,线程竣事且无其它对这个工具的引用,这个工具将由垃圾收集机制自动GC。共享工具指由多个线程共享的工具,各线程保持多个指向同一个工具的引用,任何对这个工具的修改城市在其它引用上获得浮现,共享工具一般通过Factory工场的getInstace()要领建设,单例模式就是建设共享工具的尺度实现。独享工具由于无其它指向同一工具的引用,不消担忧其它引用对工具属性的修改,在多线程情况里,也就不需要对其大概修改属性的要领加以同步,淘汰了堕落的隐患和巨大性,但由于需要为每个线程都建设工具,增加了对内存的需求和JVM GC的承担。共享工具则需要举办适当的同步(制止较大的同步块,同时防备死锁)。

尚有几种非凡工具:稳定工具和要领工具。稳定工具指工具对外不含有修改工具属性的要领(如set要领),外部要修改属性只能通过new新的实例来实现。稳定工具最大的长处就是无需担忧属性被修改,制止了潜在的bug,并能无需任何特别事情(如同步)就很好的事情在多线程情况下。如JDK的String工具就是典范的稳定工具。要领工具简朴的说就是仅包括要领,不含有属性的工具。由于没有工具属性,要领中无需举办修改属性的操纵,也就能回收static要领或单例模式,制止每次利用都要new工具,淘汰工具的利用。

那么该如何确定建设何种工具,这就要团结工具的利用方法和生命周期、工具巨细、构建花销等方面来综合思量。假如工具生命周期较长,会存在修改操纵,不能容忍其它线程对其的修改,就应该回收独享工具,如常见的Bean类。而假如工具生命周期较长,且能为各个线程共享,就可以思量共享工具。共享有2种常见环境,一种是系统全局工具,如设置属性等,各个线程应该引用同一工具,任何对这个工具的修改城市影响其它线程;另一种是由于工具建设开销较大,各线程对此工具是瞬时会见,且无需再次读取其属性,如常见的Date 工具,一般这种工具的利用是瞬时的,好比把它format成String,假如每次建设然后期待GC就会挥霍大量内存和CPU时间,较好做法就是做成共享工具,各个线程先set再利用,留意对举办set并会见的要领要同步。稳定工具一般利用在工具建设开销较小(属性较少,类条理较少),且需要能自由共享的景象。如一个工具里的常量工具,利用public static final AAA=new AAA(…) 建设。要领工具利用较广,如Util类、DAO类等,这些工具提供操纵其它工具(一般是bean工具)的接口,能对系统在条理和成果长举办解耦合。

J2EE系统优化的几点体会(二、轮回)


#p#副标题#e#

条例二:在轮回处,多下工夫

轮回作为措施编写的根基语法,可以说是到处可见。一些小的细节能带来机能上的晋升,而对轮回体的一些改写,能带来机能的大幅晋升。

好比最简朴的List遍历,会有这样的写法:for(int i=0;i

同样是对List的操纵,假如要在遍历同时举办增加和删除操纵,代码如下:for(int i=0,j=l.size();i=0;i–){l.remove(i);}。颠末测试,假如回收ArrayList,两种写法在轮回次数较少时没有太大的区别,轮回次数为1000,均为1ms以内,次数为10000,前一种为60ms阁下,后一种为1ms以内,,而次数上到100000,前一种为6000ms阁下,后一种为15ms,跟着轮回次数的增多,后一种较前一种的效率优势明明提高。

这是由Collection库ArrayList的实现抉择的,以下是JDK1.3的ArrayList源码:

public Object remove(int index) {

RangeCheck(index);

modCount++;

Object oldValue = elementData[index];

int numMoved = size – index – 1;

if (numMoved > 0)

System.arraycopy(elementData, index+1, elementData, index,

numMoved);

elementData[–size] = null; // Let gc do its work

return oldValue;

}

#p#分页标题#e#

从中我们可以看出,numMoved代表了需要举办arraycopy操纵的数量,它是由remove的位置抉择的,假如index=0,也就是删除第一个元素,则需要arraycopy后头的所有数据,

而假如index=size-1,则只需将最后一个元素设为null即可。所以从后头向前轮回remove是较量好的写法。

假如List中简直存在较多的add或remove操纵,且容量较大(如存储几万个工具),则应该回收LinkedList作为实现。LinkedList内部回收双向链表作为数据布局,比ArrayList占用较多内存空间,且随时机见操纵较慢(需要从新或尾轮回到相应位置),但插入删除操纵很快(仅需举办链表操纵,无须大量移动或拷贝)。

对付List操纵假如轮回局限较小,其实对机能影响很是小(ms级),远远不是机能瓶颈地址。但心中有着优化的意识,并力争写出简捷高效的措施应该是我们每个措施员的追求。并且一旦在轮回局限较大时,假如有了这些意识,也就能有效的消除机能隐患。

再举一个与优化无关但确实大概成为机能杀手(可以说是bug)的轮回的例子。下面是源代码:

for(; totalRead < m_totalBytes; totalRead += readBytes)

{

readBytes = m_request.getInputStream().read(m_binArray, totalRead, m_totalBytes – totalRead);

}

这个代码意图很清楚,就是将一个InputStream流读到一个byte数组中去。它利用read要领轮回读取InputStream,该要领返回读取的字节数。正常环境下,该轮回运行精采,当totalRead=m_totalBytes时,竣事轮回,byte数组被正常填充。但假如仔细看一下InputStream的read要领的说明,相识一下其返回值就会发明,返回值大概为-1,即已读到InputStream末端再继承读时。假如产生读取异常,大概呈现这个问题,而这个轮回没有查抄readBytes值是否为-1就往totalRead上加,这样再次进入轮回体继承读取InputStream,又返回-1,继承轮回。如此轮回直到int溢出才会跳出轮回。而这个轮回也就成了实实在在的CPU杀手,可以占去大量的CPU时间(取决于操纵系统)。其实办理很简朴,对readBytes举办判定,假如为-1则跳出轮回。

这个例子汇报我们:对轮回必然要搞清轮回的轮回局限、每次轮回体执行时间、轮回竣事条件包罗异常环境等,只有这样才气写出高效且没有隐患的代码。

    关键字:

在线提交作业