`
runfriends
  • 浏览: 228879 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java开发中常见的简单效率问题

阅读更多

 

本文要说的内容都是小问题,为编写代码图省劲而出的小问题。这样的代码在代码量小、执行频率低、并发量低、占用内存低、占用cpu时间低的情况下没什么,一旦这样的代码在应用中达到一定数量,或在执行频率、并发量、内存占用量、cpu时间消耗达到一个临界值的时候,应用的运行效率就会显著降低,甚至会使响应时间和吞吐量达到难以忍受的程度。

本文只说其中最常见的两个,一个是使用“+”拼字符串,一个是使用“+”拼sqlhql

编写代码的时候,用“+”拼字符串确实很方便。要拼的字符串内容包含在变量里,在用“+”拼字符串的代码行加个断点调试一下就会知道,“+”实际上就是创建了一个StringBuilder对象然后调用append方法最后再调用toString方法,这就是一个“+”做的全部工作。如果n个“+”参数计算,整个拼接过程创建了n个字符串对象,和nStringBuilder对象,调用了ntoString方法,这就是用“+”拼字符串效率低的原因所在,即耗堆内存又消耗时间。

我们不妨做一个测试。

//测试+

public static void test1(){

    String str=””;

    long s=System.currentTimeMillis();

    for(int i=0;i<10000;i++){

        str+=’a’;

    }

        System.out.println(System.currentTimeMillis()-s);

}

 

//测试StringBuilder

public static void test2(){

    StringBuilder builder=new StringBuilder();

    long s=System.currentTimeMillis();

    for(int i=0;i<10000;i++){

        builder.append('a');

    }

    String str=builder.toString();

    System.out.println(System.currentTimeMillis()-s);

}

不妨运行下上面两段代码,第一段代码消耗的内存要比第二段大的多,默认jvm堆内存可能会在运行第一段代码时抛出OOM,而且运行第一段代码耗时是第二段的1000多倍(视机器硬件不同,会有差异,不过耗时绝对明显)。

另一方面,如果用“+”将连接多个字面量连接成新字符串,eclipse jdt编译器会在编译时就完成这个连接的计算工作。(javac是不是也这样,我没有测试过。对于编译器的问题就不要有疑问了,eclipse确实按照java标准实现了一个编译器,据说比javac要好的多,另据说javacbug。)

最后如果使用连+拼字符串,而不是在一个方法内将拼字符串的操作分散在多处,这个时候编译器会把连+编译成一个StringBuilder对象和若干次append调用。

综上所述,如果一个字符串太长,不利于阅读代码,可以用“+”连接配合缩进增强代码可读性,否则在要连接的字符串超过一+时最好使用StringBuilder代替。

另外,jdk还提供了所有方法都是线程安全的StringBuffer,由于它的方法都用synchronized声明,单线程性能比StringBuilder略低;而且带synchronized声明的方法实际上锁定的是方法所在的Class对象,因此随着使用StringBuffer的代码越来越多,线程越来越多,因synchronized同步导致的效率问题也会越来越凸显,这跟应用中StringBuffer对象的数量无关,只跟使用StringBuffer的线程数和代码量有关,因为锁是加在StringBuffer.class对象上的,只要线程里面使用的StringBuffer类都是同一个ClassLoader对象加载的就会如此,而绝大多数情况下,jdk本身的类一定是由根类加载器加载。

至于直接把查询参数拼到sqlhql的代码风格也会造成与“+”连接字符串类似的结果。hibernate会首先分析hql,构造出一个hql语法树,这个语法树由一系列对象构成,hibernate session缓存、二级缓存、各种关联映射关系都依赖于这个hql语法树,并且将利用hql语法树翻译出sql;数据库也会分析sql,构造出一个sql语法树,并最终完成数据库表的增删改查。一条hql对应一个语法树,分析完成后,即使hql结构相同,仅仅参数值不同,也会被hibernate判断为不同的hql;对于完成分析的hqlhibernate会将分析结果缓存起来,以备以后使用。sql对于数据库亦然。当然由于内存有限,如果sql/hql,不论hibernate还是数据库都不会缓存应用运行期出现的所有语法树,最不常用的语法树会被清除。所以根据以上分析,把查询参数拼到sql/hql里面同样是运行期即耗内存又耗时间的做法。使用占位符的方式构造sql/hql会大大减少内存消耗和降低运行时间。

将参数作为sql/hql的一部分还会引起一个严重问题,就是sql注入,如果参数里面有sql/hql片断,这个片断就会被拼到要执行的sql/hql里面,这可能会带来灾难性的后果,而造成这一切的原因仅仅是因为没有使用占位符sql/hql。对此不必怀疑,使用占位符sql/hql就能杜绝sql注入。原因就在于传入参数前sql/hql已经被解析完成,语法树已经构建完毕,任何传入的参数都不会再被当作sql/hql的一部分处理。

另外,如果使用hibernate作为orm框架,最好增删改查都使用hibernate完成,不要绕过hibernate直接操作jdbc。保持一致的代码风格是一方面,另一方面也是更重要的,全部使用hibernate操作增删改查,任何数据变更hibernate都能管理的到,会进一步通过hibernate提升针对数据库操作的运行效率。而且hql除了支持查询,也早就支持updatedelete了。现在hibernate除了批量更新、删除尚不支持外,可以很方便的通过hql完成增删改查工作。

最近听到很多人讨论不推荐在项目中使用太多框架,都想除spring以外杜绝第三方框架,其实个人认为大可不必,应用效率的瓶颈不在框架,而在于使用它们的方式、代码风格和架构设计。优秀的架构设计配合合理应用的框架以及高效的代码完全能够实现高效的应用。应用效率低下并不在于使用什么框架,如果由于框架本身引发了低下的效率,这个框架早就不会存在了,而它们能够长久的生存下来本身就足够说明问题。同时合理选择框架也会大大提高开发效率。因此如果遇到了性能或效率问题还是应首先从应用自身的架构、代码规范与代码风格上着手解决。将问题归绺于框架,是南辕北辙,甚至逃避责任。

最后,关于框架再多说一些。个人并不推崇惟框架是从,个人认为在产品早期为了追求尽快面世,可以采用框架开发;在小规模应用或技术积累尚不够充分时应采用框架开发;而在应用规模达到一定程度的时候,这时应该已经有了足够的技术积累去实现有自主知识产权的框架。纵观国内外各大互联网公司所走过的技术路线,莫不如是。关于它们的技术发展史网上有很多介绍的文章,甚至一些来自这些公司的架构师也亲自发文分享自己的心路历程与公司的技术路线。有兴趣的朋友不妨看一下。

 

0
0
分享到:
评论
2 楼 runfriends 2012-11-24  
laogao3232 写道
那段示例代码是开玩笑的吗?

不好意思。这段测试逻辑是2009年测试的,原来的代码早就丢了。这一段是我在编辑器里写的。有语法错误,实在抱歉。
我把错误改了。
1 楼 laogao3232 2012-11-24  
那段示例代码是开玩笑的吗?

相关推荐

    Java开发常见问题汇总.ppt

    在Java开发过程中,遇到...总之,Java开发中的问题涉及环境配置、IDE使用、代码编写等多个方面,了解这些问题的解决方案,有助于提升开发效率和代码质量。在日常工作中,不断学习和积累经验,才能更好地应对各种挑战。

    java常用开发词汇

    本文档旨在整理java开发中常见的词汇,为尚学堂学员孙 BO 同学整理。孙 BO 同学坚持将自己在开发中碰到的词汇一一整理,彻底贯彻了高淇老师的”见一个消灭一个”的原则。 下面是从给定的文件中生成的相关知识点: ...

    java开发中常用的包

    这里提到的"java开发中常用的包"压缩文件,包含了大约40个Java开发中非常重要的JAR包。下面将详细介绍一些常见的JAR包及其在Java开发中的作用。 1. **Apache Commons**: Apache Commons 是一系列小型、实用的Java...

    JAVA开发常用工具安装包

    JAVA开发常用工具安装包 Java是一种广泛应用于软件开发的编程语言,为了提高开发效率和质量,开发者需要安装和配置各种开发工具。以下是JAVA开发常用工具安装包的详细介绍: Eclipse Eclipse是最流行的Java开发...

    java学习笔记,JavaWeb开发中常见问题总结

    【Java学习笔记】JavaWeb开发中常见问题总结 在JavaWeb开发中,开发者经常会遇到各种问题,这些问题涵盖从基础语法到高级设计模式的各个方面。以下是一些关键知识点的概述: 1. **Java基础知识**: - **Classpath...

    Java代码开发常见问题培训

    Java代码开发常见问题培训涵盖了性能影响、稳定性、编程易错点、系统健壮性以及数据库连接管理等多个方面,目的是帮助Java程序员规避开发中常见的错误,确保代码质量和系统稳定性。 首先,性能影响与稳定性方面,...

    java项目开发常见问题分析

    总结来说,Java项目开发中的常见问题涉及多个层面,从基本的编码规范到复杂的性能优化,再到框架的熟练运用。开发者需要不断学习和实践,以提升个人技能,减少问题的发生,从而提高项目的成功率和质量。通过规范的...

    java开发中常用API

    Java开发中的常用API是程序员日常工作中不可或缺的一部分,它包含了各种工具类、接口和类,用于实现各种功能。这里我们主要关注几个重要的API组件,包括W3CSchool的基础教程,MySQL5中文参考手册,jQuery 1.8.3的...

    java开发常用工具类

    在Java开发中,工具类是程序员经常会用到的代码库,它们提供了许多便捷的方法,以简化常见的编程任务。本文将详细解析"java开发常用工具类"中的关键知识点,包括日历、时间处理、Excel导出、网络请求、流操作、数据...

    Java项目开发常见问题分析

    在Java项目开发过程中,开发者经常会遇到一系列的问题,这些问题可能涉及到编程语法、运行环境、框架应用、性能优化等多个...通过阅读"Java项目开发常见问题分析.pdf"这份文档,你将能够获取更深入的见解和解决方法。

    Java业务开发常见错误.zip

    本压缩包文件"Java业务开发常见错误.zip"聚焦于Java开发中的一些常见陷阱,通过一系列文档帮助开发者理解和避免这些问题。 首先,"00丨开篇词丨业务代码真的会有这么多坑?.pdf"引出了一个核心问题,即业务代码的...

    MyEclipse 6 Java 开发中文教程(源代码)

    在Java开发方面,它提供了一流的代码编辑、调试和重构功能,使得代码编写更加高效便捷。 教程中的源代码是学习的核心部分,它们涵盖了基本的Java编程概念,如类、对象、继承、多态以及异常处理等。同时,这些代码也...

    java开发List提高效率

    Java 开发中,List 是一个常用的数据结构,经常需要将 List 转换为逗号分隔的字符串,以便于数据的存储和传输。提高 List 转换效率是 Java 开发中非常重要的一方面,本文将讨论如何将 List 转换为逗号分隔的字符串,...

    java常见14种开发工具

    以下是对描述中提到的四种常见的Java开发工具的详细解析: 1. JDK(Java Development Kit):JDK是Java开发的基础,包含了Java运行环境(JRE)、Java编译器(javac)、Java文档生成器(javadoc)以及其他必要的工具...

    java开发常用jar包

    在Java开发中,jar包是不可或缺的组成部分,它们包含了预编译的类和接口,使得开发者可以方便地引入和使用各种功能。以下是对标题和描述中提到的几个关键知识点的详细解释: 1. **Http**: 在Java中处理HTTP请求通常...

    Java开发手册(黄山版)

    《Java开发手册(黄山版)》是阿里巴巴在2022年发布的一份全面而详细的Java编程指南,旨在规范Java开发过程中的最佳实践,提升代码质量和团队协作效率。该手册覆盖了Java语言的基础、进阶、设计模式、并发编程、性能...

    java开发手册.docx

    对于Java开发人员来说,手册不仅是一份技术指南,更是一个成长伙伴,可以帮助他们在日常开发中避免常见陷阱,提升专业技能。对于前端开发者,它提供了必要的Java基础知识,有助于理解后端逻辑,增强前后端协作。对于...

Global site tag (gtag.js) - Google Analytics