提高代码效率的方法.ppt

上传人:苏美尔 文档编号:11879300 上传时间:2021-10-10 格式:PPT 页数:41 大小:329KB
返回 下载 相关 举报
提高代码效率的方法.ppt_第1页
第1页 / 共41页
提高代码效率的方法.ppt_第2页
第2页 / 共41页
提高代码效率的方法.ppt_第3页
第3页 / 共41页
提高代码效率的方法.ppt_第4页
第4页 / 共41页
提高代码效率的方法.ppt_第5页
第5页 / 共41页
点击查看更多>>
资源描述

《提高代码效率的方法.ppt》由会员分享,可在线阅读,更多相关《提高代码效率的方法.ppt(41页珍藏版)》请在三一文库上搜索。

1、提高代码效率的方法,山水瑞通网络科技有限责任公司,优化循环体,循环是比较重复运行的地方,如果循环次数很大,循环体内不好的代码对效率的影响就会被放大而变的突出。让我们看看下面的代码片:.Vector vect = new Vector(1000);.for( inti=0; ivect.size(); i+).for循环部分改写成:int size = vect.size(); for( int i=0; i size; i+).如果size=1000,就可以减少1000次size()的系统调用开销,避免了循环体重复调用。,少用new初始化一个实例,尽量少用new来初始化一个类的实例,当一个对象

2、是用new进行初始化时,其构造函数链的所有构造函数都被调用到,所以new操作符是很消耗系统资源的,new一个对象耗时往往是局部变量赋值耗时的上千倍。同时,当生成对象后,系统还要花时间进行垃圾回收和处理。当new创建对象不可避免时,注意避免多次的使用new初始化一个对象。尽量在使用时再创建该对象。如:NewObject object = new NewObject();int value;if(i0 )value =object.getValue();,少用new初始化一个实例,上面一段代码可以修改为:int value;if(i0 )NewObject object = new NewObje

3、ct();Value =object.getValue();另外,应该尽量重复使用一个对象,而不是声明新的同类对象。一个重用对象的方法是改变对象的值,如可以通过setValue之类的方法改变对象的变量达到重用的目的。,在Java中,一切都是对象,如果有方法(Method)调用,处理器先要检查该方法是属于哪个对象,该对象是否有效,对象属于什么类型,然后选择合适的方法并调用。 可以减少方法的调用,同样一个方法:public void CallMethod(int i )if( i =0 )return;. / 其他处理如果直接调用int i = 0;.CallMethod(i);,选择合适的方法调

4、用,选择合适的方法调用,上面的代码,就应该写成:int i = 0;.if( i =0 )CallMethod(i);不影响可读性等情况下,可以把几个小的方法合成一个大的方法。另外,在方法前加上final,private关键字有利于编译器的优化。,尽量使用局部变量,调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。另外,依赖于具体的编译器/JVM,局部变量还可能得到进一步优化。,尽量使用局部变量,例子: public class USV private int _sum; private s

5、tatic int _staticSum; void getSum (int values) for (int i=0; i values.length; i+) _sum += valuesi; / violation. void getSum2 (int values) for (int i=0; i values.length; i+) _staticSum += valuesi; 更正: 如果可能,请使用局部变量作为你经常访问的变量。 你可以按下面的方法来修改getSum()方法: void getSum (int values) int sum = _sum; / temporary

6、 local variable. for (int i=0; i values.length; i+) sum += valuesi; _sum = sum; ,String与StringBuffer的使用技巧,1、字符串在JAVA中被广泛的使用,但是由于String 对象是不可改变的, 所以如果我们试图将两个String对象相加的时候,它实际的执行是产生一个中间对象StringBuffer,并调用它的append ()法来进行相加的,最后调用StringBufffer的toString()方法来返回一个String的对象,如果只是一般的相加差别不大,但是如果是在循环中,性能差距就较明显 注:

7、String s = “a” + “b” + “c”,实际上在编译后是String s=“abc”,执行时不存在相加问题 2、在字符串相加的时候,如果该字符串只有一个字符的话 如:String str = s + “d” 应该换作 string = s + d来执行。 3、由于在创建一个StringBuffer对象时, StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,如果可以的话 ,在创建StringBuffer的时候应指定大小,这样就避免了在容

8、量不够的时候自动增长,以提高性能。,返回,返回,尽可能的使用Java自身提供的API,上面那段代码,如果使用Java提供的API,就可以提高性能:例子: public class IRB void method () int array1 = new int 100; for (int i = 0; i array1.length; i+) array1 i = i; int array2 = new int 100; for (int i = 0; i array2.length; i+) array2 i = array1 i; / Violation 同样的一个规则是,当有大量数据的复制

9、时,应该使用System.arraycopy()。,尽可能的使用Java自身提供的API,更正: public class IRB void method () int array1 = new int 100; for (int i = 0; i array1.length; i+) array1 i = i; int array2 = new int 100; System.arraycopy(array1, 0, array2, 0, 100); ,不要重复初始化变量,默认情况下,调用类的构造函数时, Java会把变量初始化成确定的值:所有的对象被设置成null,整数变量(byte、sh

10、ort、int、long)设置成0,float和double变量设置成0.0,逻辑值设置成false。当一个类从另一个类派生时,这一点尤其应该注意,因为用new关键词创建一个对象时,构造函数链中的所有构造函数都会被自动调用。,避免不需要的造型操作,所有的类都是直接或者间接继承自Object。同样,所有的子类也都隐含的“等于”其父类。那么,由子类造型至父类的操作就是不必要的了。 例子: class UNC String _id = UNC; class Dog extends UNC void method () Dog dog = new Dog (); UNC animal = (UNC)d

11、og; / not necessary. Object o = (Object)dog; / not necessary. 更正: class Dog extends UNC void method () Dog dog = new Dog(); UNC animal = dog; Object o = dog; ,如果只是查找单个字符的话,用charAt()代替startsWith(),用一个字符作为参数调用startsWith()也会工作的很好,但从性能角度上来看,调用String API无疑是错误的! 例子: public class PCTS private void method(S

12、tring s) if (s.startsWith(a) / violation / . 更正 将startsWith() 替换成charAt(). public class PCTS private void method(String s) if (a = s.charAt(0) / . ,不要在循环中调用synchronized(同步)方法,方法的同步需要消耗相当大的资源,在一个循环中调用它绝对不是一个好主意。 例子: import java.util.Vector; public class SYN public synchronized void method (Object o)

13、private void test () for (int i = 0; i vector.size(); i+) method (vector.elementAt(i); / violation private Vector vector = new Vector (5, 5); ,不要在循环中调用synchronized(同步)方法,更正: 不要在循环体中调用同步方法,如果必须同步的话,推荐以下方式: import java.util.Vector; public class SYN public void method (Object o) private void test () sy

14、nchronized/在一个同步块中执行非同步方法 for (int i = 0; i vector.size(); i+) method (vector.elementAt(i); private Vector vector = new Vector (5, 5); ,oracle的SQL语句尽量使用大写,在JAVA + ORACLE 的应用系统开发中,java中内嵌的SQL语句尽量使用大写的形式,以减轻ORACLE解析器的解析负担。,减少I/O操作,尽量减少I/O操作: 输入/输出(I/O)包括很多方面,我们知道,进行I/O操作是很消耗系统资源的。程序中应该尽量少用I/O操作。使用时可以注

15、意: . 合理控制输出函数System.out.println()对于大多时候是有用的,特别是系统调试的时候,但也会产生大量的信息出现在控制台和日志上,同时输出时,有序列化和同步的过程,造成了开销。特别是在发行版中,要合理的控制输出,可以在项目开发时,设计好一个Debug的工具类,在该类中可以实现输出开关,输出的级别,根据不同的情况进行不同的输出的控制。 尽量使用缓存: 读写内存要比读写硬盘上的文件要快很多,应尽可能使用缓冲,以便直接从内存中读取数据。尽可能使用带有Buffer的类代替没有Buffer的类,如可以用BufferedReader 代替Reader,用BufferedWriter代

16、替Writer来进行处理I/O操作。同样可以用BufferedInputStream代替InputStream都可以获得性能的提高,即时关闭I/O流操作,Java 编程过程中,I/O流操作时务必小心,在使用完毕后,及时关闭以释放资源。因为对这些大对象的操作会造成系统大的开销,稍有不慎,会导致严重的后果。,在finally块中关闭Stream,程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。 例子: import java.io.*; public class CS public stati

17、c void main (String args) CS cs = new CS (); cs.method (); public void method () try FileInputStream fis = new FileInputStream (CS.java); int count = 0; while (fis.read () != -1) count+; System.out.println (count); fis.close (); catch (FileNotFoundException e1) catch (IOException e2) 更正: 在最后一个catch后

18、添加一个finally块,对象使用完毕应手动置成null,由于JVM的有其自身的GC机制,不需要程序开发者的过多考虑,从一定程度上减轻了开发者负担,但同时也遗漏了隐患,过分的创建对象会消耗系统的大量内存,严重时会导致内存泄露,因此,保证过期对象的及时回收具有重要意义。JVM回收垃圾的条件是:对象不在被引用;然而,JVM的GC并非十分的机智,即使对象满足了垃圾回收的条件也不一定会被立即回收。所以,建议我们在对象使用完毕,应手动置成null。,尽量采用lazy loading 的策略,例如: String str = “aaa”; if(i = 1) list.add(str); 应替换为: if

19、(i = 1) String str = “aaa”; list.add(str); ,慎用异常,异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。异常只能用于错误处理,不应该用来控制程序流程。,不要在循环中使用 try catch,Try catch() 应把其放置在最外层。,集合类优化问题,集合类在此Java编程中被广泛地使用,一个集合类就是将一

20、组对象组装成一个对象Java的集合类框架由一些接口(如Collection、List、Set、Map)和一些为通用目的而实现的类(如Vector,ArrayList、Hashtable等等)组成,这些类里,有些提供了某种排序算法,有的提供了同步的方法,有如此多的集合类,在具体使用过程中,我们如何根据自己的需要选择合适的集合类,将对程序的性能产生很大的影响,下面将一些常用的类进行比较: Vector和ArrayList Vector和ArrayList在使用上非常相似,都可用来表示一组数量可变的对象应用的集 合,并且可以随机地访问其中的元素。它们的区别如下: 1、Vector的方法都是同步的(S

21、ynchronized),是线程安全的(thread-safe),而ArrayList 的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好. 2、当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而 ArrayList只增加50%的大小,这样ArrayList就有利于节约内存空间。 Hashtable和HashMap 它们的性能方面的比较类似 Vector和ArrayList,比如Hashtable的方法是同步的,而 HashMap的不是。 当它们中的元素超过它的初始大小时,都会将它的容量翻倍。,ArrayList

22、和LinkedList 对于处理一列数据项,Java提供了两个类ArrayList和LinkedList,ArrayList的内部实现是基于内部数组Object,所以从概念上讲,它更象数组,但LinkedList的内部实现是基于一组连接的记录,所以,它更象一个链表结构,所以,它们在性能上有很大的差别。 (1)在ArrayList的前面或中间插入数据时,你必须将其后的所有数据相应的后移,这样必然要花费较多时间,所以,当你的操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能。 (2)访问链表中的某个元素时,就必须从链表的一端开

23、始沿着连接方向一个一个元素地去查找,直到找到所需的元素为止,所以,当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。 注意:在Java集合框架中的大部分类的大小是可以随着元素个数的增加而相应的增加的,我们似乎不用关心它的初始大小,但如果我们考虑类的性能问题时,就一定要考虑尽可能地设置好集合对象的初始大小,这将大大提高代码的性能,比如,Hashtable缺省的初始大小为11,载入因子为0.75,即如果其中的元素个数超过7个,它就必须增加大小并重新组织元素,所以,如果你知道在创建一个新的Hashtable对象时就知道元素的确切数目如为

24、12,那么,就应将其初始大小设为12/0.75=16,这样,就可以避免重新组织内存并增加大小。(默认Vector ArrayList 10个大小,Hashtable 11,HashMap 16),集合类优化问题,返回,不用保存太多的信息在HttpSession中,很多时候,存储一些对象在HttpSession中是有必要的,可以加快系统的开发,如网上商店系统会把购物车信息保存在该用户的Session中,但当存储大量的信息或是大的对象在会话中时,是有害的,特别是当系统中用户的访问量很大,对内存的需求就会很高。,不用保存太多的信息在HttpSession中,清除SESSION: 通常情况,当达到设定

25、的超时时间时,同时有些Session没有了活动,服务器会释放这些没有活动的Session,. 不过这种情况下,特别是多用户并访时,系统内存要维护多个的无效Session。当用户退出时,应该手动释放,回收资源,实现如下:HttpSession theSession = request.getSession();/ 获取当前Sessionif(theSession != null)theSession.invalidate(); / 使该Session失效,在JSP页面中关闭无用的会话,一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用HttpSer

26、vletRequest.getSession(true)这样的语句时才被创建,注意如果JSP没有显示的使用 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的session对象的来历。由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。对于那些无需跟踪会话状态的页面,关闭自动创建的会话可以节省一些资源。使用如下page指令:,使用快速度的Jdbc驱动,JDBC API包括两种实现接口形

27、式,一种是纯Java实现的驱动,一种利用ODBC驱动和数据库客户端实现,具体有四种驱动模式: 第一类JDBC驱动程序是JDBC-ODBC桥再加上一个ODBC驱动程序。建议第一类驱动程序只用于原型开发,而不要用于正式的运行环境。桥接驱动程序由Sun提供,它的目标是支持传统的数据库系统。Sun为该软件提供关键问题的补丁,但不为该软件的最终用户提供支持。一般地,桥接驱动程序用于已经在ODBC技术上投资的情形,例如已经投资了Windows应用服务器。 尽管Sun提供了JDBC-ODBC桥接驱动程序,但由于ODBC会在客户端装载二进制代码和数据库客户端代码,这种技术不适用于高事务性的环境。另外,第一类J

28、DBC驱动程序不支持完整的Java命令集,而是局限于ODBC驱动程序的功能,这种驱动方式也叫胖客户,主要用于低并发请求,大数据量传输的应用。,使用快速度的Jdbc驱动,第二类JDBC驱动程序是本机API的部分Java代码的驱动程序,用于把JDBC调用转换成主流数据库API的本机调用。这类驱动程序也存在与第一类驱动程序一样的性能问题,即客户端载入二进制代码的问题,而且它们被绑定了特定的平台。 第二类驱动程序要求编写面向特定平台的代码,主流的数据库厂商,例如Oracle和IBM,都为它们的企业数据库平台提供了第二类驱动程序,使用这些驱动程序的开发者必须及时跟进不同数据库厂商针对不同操作系统发行的各

29、个驱动程序版本。 另外,由于第二类驱动程序没有使用纯Java的API,把Java应用连接到数据源时,往往必须执行一些额外的配置工作。很多时候,第二类驱动程序不能在体系结构上与大型主机的数据源兼容;即使做到了兼容,效果也是比较差。,使用快速度的Jdbc驱动,第三类JDBC驱动程序是面向数据库中间件的纯Java驱动程序,JDBC调用被转换成一种中间件厂商的协议,中间件再把这些调用转换到数据库API。第三类JDBC驱动程序的优点是它以服务器为基础,也就是不再需要客户端的本机代码,这使第三类驱动程序要比第一、二两类快。另外,开发者还可以利用单一的驱动程序连接到多种数据库。,使用快速度的Jdbc驱动,第

30、四类JDBC驱动程序是直接面向数据库的纯Java驱动程序,即所谓的“瘦”(thin)驱动程序,它把JDBC调用转换成某种直接可被DBMS使用的网络协议,这样,客户机和应用服务器可以直接调用DBMS服务器。对于第四类驱动程序,不同DBMS的驱动程序不同。因此,在一个异构计算环境中,驱动程序的数量可能会比较多。但是,由于第四类驱动程序具有较高的性能,能够直接访问DBMS,所以这一问题就不那么突出了, 这种驱动方式,主要用于高并发,低数据量请求的应用中。,Jdbc链接池,使用Jdbc链接池 为了提高访问数据库的性能,我们还可以使用JDBC 2.0的一些规范和特性,JDBC是占用资源的,在使用数据库连

31、接时可以使用连接池Connection Pooling,避免频繁打开、关闭Connection。而我们知道,获取Connection是比较消耗系统资源的。Connection缓冲池:当一个应用程序关闭一个数据库连接时,这个连接并不真正释放而是被循环利用,建立连接是消耗较大的操作,循环利用连接可以显著的提高性能,因为可以减少新连接的建立。一个通过DataSource获取缓冲池获得连接,并连接到一个CustomerDB数据源的代码演示如下:Context ctx = new InitialContext();DataSource dataSource = (DataSource) ctx.look

32、up(jdbc/CustomerDB);Connection conn = dataSource.getConnection(password,username);,缓存DataSorce,缓存DataSorce 一个DataSource对象代表一个实际的数据源。这个数据源可以是从关系数据库到表格形式的文件,完全依赖于它是怎样实现的,一个数据源对象注册到JNDI名字服务后,应用程序就可以从JNDI服务器上取得该对象,并使用之和数据源建立连接。通过上面的例子,我们知道DataSource是从连接池获得连接的一种方式,通过JNDI方式获得,是占用资源的。为了避免再次的JNDI调用,可以系统中缓存要使用的DataSource。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 科普知识


经营许可证编号:宁ICP备18001539号-1