11个简单的Java性能调优技巧,拿走不谢~

2020-06-03 10:06:47

大多数java开发人员理所当然地以为性能优化很复杂,需要大量的经验和知识。好吧,不能说这是完全错误的。优化应用程序以获得最佳性能不是一件容易的事情。


 

但是,这并不意味着如果你不具备这些知识,就不能做任何事情。这里有11个易于遵循的建议和最佳实践可以帮助你创建一个性能良好的应用程序。

大部分建议是针对Java的。但也有若干建议是与语言无关的,可以应用于所有应用程序和编程语言。


 

1、在必要之前不要优化

你应该遵循常见的最佳实践做法并尝试高效地实现用例。但是,这并不意味着在你证明必要之前,你应该更换任何标准库或构建复杂的优化。


 

在大多数情况下,过早优化不但会占用大量时间,而且会使代码变得难以阅读和维护。更糟糕的是,这些优化通常不会带来任何好处,因为你花费大量时间来优化的是应用程序的非关键部分。


 

那么,你如何证明你需要优化一些东西呢?

首先,你需要定义应用程序代码的速度得多快,例如,为所有API调用指定最大响应时间,或者指定在特定时间范围内要导入的记录数量。在完成这些之后,你就可以测量应用程序的哪些部分太慢需要改进。

2.使用分析器查找真正的瓶颈

在确定了应用程序的某些部分需要改进后,那么从哪里开始呢?


 

你可以用两种方法来解决问题:

·查看你的代码,并从看起来可疑或者你觉得可能会产生问题的部分开始。

·使用分析器并获取有关代码每个部分的行为和性能的详细信息。


 

很明显,基于分析器的方法可以让你更好地理解代码的性能影响,并使你能够专注于最关键的部分,高效便捷。
 

3.为整个应用程序创建性能测试套件

你应该总是定义一个测试整个应用程序的性能测试套件,并在性能改进之前和之后运行它。


 

这些额外的测试运行将帮助你识别更改的功能和性能副作用,并确保不会导致弊大于利的更新。如果你工作于被应用程序若干不同部分使用的组件,如数据库或缓存,那么这一点就尤其重要。

4.首先处理最大的瓶颈

在创建测试套件并使用分析器分析应用程序之后,你可以列出一系列需要解决以提高性能的问题。这很好,但它仍然不能回答你应该从哪里开始的问题。你可以专注于速效方案,或从最重要的问题开始。


 

速效方案一开始可能会很有吸引力,因为你可以很快显示第一个成果。但有时,可能需要你说服其他团队成员或管理层认为性能分析是值得的——因为暂时看不到效果。


 

但总的来说,建议首先处理最重要的性能问题。这将为你提供最大的性能改进,而且可能再也不需要去解决其中一些为了满足性能需求的问题。

常见的性能调整技巧到此结束。下面让我们仔细看看一些特定于Java的技巧。


 

5.使用StringBuilder以编程方式连接String

有很多不同的选项来连接Java中的String。例如,你可以使用简单的+或+ =,以及StringBuffer或StringBuilder。


 

那么,你应该选择哪种方法?


 

答案取决于连接String的代码。如果你是以编程方式添加新内容到String中,例如在for循环中,那么你应该使用StringBuilder。它很容易使用,并提供比StringBuffer更好的性能。但请记住,与StringBuffer相比,StringBuilder不是线程安全的,可能不适合所有用例。


 

你只需要实例化一个新的StringBuilder并调用append方法来向String中添加一个新的部分。在你添加了所有的部分之后,你就可以调用toString()方法来检索连接的String。


 

下面的代码片段显示了一个简单的例子。在每次迭代期间,这个循环将i转换为一个String,并将它与一个空格一起添加到StringBuilder sb中。所以,最后,这段代码将在日志文件中写入“This is a test0 1 2 3 4 5 6 7 8 9”。

StringBuilder sb = new StringBuilder(“This is a test”);for (int i=0; i<10; i++) {
sb.append(i);
sb.append(” “);
}log.info(sb.toString());

正如在代码片段中看到的那样,你可以将String的第一个元素提供给构造方法。这将创建一个新的StringBuilder,新的StringBuilder包含提供的String和16个额外字符的容量。当你向StringBuilder添加更多字符时,JVM将动态增加StringBuilder的大小。


 

如果你已经知道你的String将包含多少个字符,则可以将该数字提供给不同的构造方法以实例化具有定义容量的StringBuilder。这进一步提高了效率,因为它不需要动态扩展其容量。

6.使用+连接一个语句中的String

当你用Java实现你的第一个应用程序时,可能有人告诉过你不应该用+来连接String。如果你是在应用程序逻辑中连接字符串,这是正确的。字符串是不可变的,每个字符串的连接结果都存储在一个新的String对象中。这需要额外的内存,会减慢你的应用程序,特别是如果你在一个循环内连接多个字符串的话。


 

在这些情况下,你应该遵循技巧5并使用StringBuilder。


 

但是,如果你只是将字符串分成多行来改善代码的可读性,那情况就不一样了。

Query q = em.createQuery(“SELECT a.id, a.firstName, a.lastName ”
+ “FROM Author a ”
+ “WHERE a.id = :id”);

在这些情况下,你应该用一个简单的+来连接你的字符串。Java编译器会对此优化并在编译时执行连接。所以,在运行时,你的代码将只使用1个String,不需要连接。

7.尽可能使用基元

避免任何开销并提高应用程序性能的另一个简便而快速的方法是使用基本类型而不是其包装类。所以,最好使用int来代替Integer,使用double来代替Double。这允许JVM将值存储在堆栈而不是堆中以减少内存消耗,并作出更有效的处理。

8.试着避免BigInteger和BigDecimal

BigInteger和BigDecimal比简单的long或double需要更多的内存,并且会显著减慢所有计算。


 

所以,你如果需要额外的精度,或者数字将超过long的范围,那么最好三思而后行。这可能是你需要更改以解决性能问题的唯一方法,特别是在实现数学算法的时候。

9.首先检查当前日志级别

在你创建调试消息之前,始终应该首先检查当前日志级别。否则,你可能会创建一个之后会被忽略的日志消息字符串。


 

这里有两个反面例子。

// don’t do thislog.debug(“User [” + userName + “] called method X with [” + i + “]”);// or thislog.debug(String.format(“User [%s] called method X with [%d]”, userName, i));

在上面两种情况中,你都将执行创建日志消息所有必需的步骤,在不知道日志框架是否将使用日志消息的前提下。因此在创建调试消息之前,最好先检查当前的日志级别。

// do thisif (log.isDebugEnabled()) {    log.debug(“User [” + userName + “] called method X with [” + i + “]”);
}


 

10.使用Apache Commons StringUtils.Replace

而不是String.replace

一般来说,String.replace方法工作正常,效率很高,尤其是在使用Java 9的情况下。但是,如果你的应用程序需要大量的替换操作,并且没有更新到最新的Java版本,那么我们依然有必要查找更快和更有效的替代品。


 

有一个备选答案是Apache Commons Lang的StringUtils.replace方法。它只需要很小的改动。即添加Apache Commons Lang项目的Maven依赖项到应用程序pom.xml中,并将String.replace方法的所有调用替换为StringUtils.replace方法。

// replace this
test.replace(“test”, “simple test”);
// with this
StringUtils.replace(test, “test”, “simple test”);


 

11.缓存昂贵的资源,如数据库连接

缓存是避免重复执行昂贵或常用代码片段的流行解决方案。总的思路很简单:重复使用这些资源比反复创建新的资源要便宜。


 

一个典型的例子是缓存池中的数据库连接。新连接的创建需要时间,如果你重用现有连接,则可以避免这种情况。


 

你还可以在Java语言本身找到其他例子。例如,Integer类的valueOf方法缓存了-128到127之间的值。你可能会说创建一个新的Integer并不是太昂贵,但是由于它经常被使用,以至于缓存最常用的值也可以提供性能优势。


 

但是,当你考虑缓存时,请记住缓存实现也会产生开销。你需要花费额外的内存来存储可重用资源,因此你可能需要管理缓存以使资源可访问,以及删除过时的资源。


 

所以,在开始缓存任何资源之前,请确保实施缓存是值得的,也就是说必须足够多地使用它们。

版权声明:转载文章和图片均来自公开网络,版权归作者本人所有,推送文章除非无法确认,都会注明作者和来源。如出处有误或侵犯到原作者权益,请与我们联系删除或授权事宜,感谢原作者。

本文由中软卓越(西安)汇集整理,转载请注明作者及出处。

如需学习java、UI设计、软件测试、Python、大数据、嵌入式、Linxu云计算,请点击咨询,加入我们让你的未来不再迷茫。

关于我们

【中软卓越】-中软国际旗下高端教育品牌,是中软国际有限公司投资的大型人才服务机构,是中软国际人才战略的核心组成部分之一,承担集团发展过程中人才储备和培养的任务;专注IT培训37年,国内高端IT培训品牌,教育部指定官方IT人才培训机构。专注java培训、UI设计培训、软件测试培训、Python培训、大数据培训、嵌入式培训、Linxu云计算培训等培训课程。217家合作院校,880家合作企业,真实项目实战,素质拓展,职业规划。零首付,100%保障就业,先就业,后付款。

最牛逼的毕业学员入职名企享受高薪就业。880家合作企业,年培育学员人数逾6000人,毕业学员就职于中软国际、百度、腾讯、阿里巴巴、IBM、华为科技、中兴通讯、软通动力等知名企业。

还有什么疑问?我们全面为你解答!为您提供一对一专人服务,请点击下方咨询

  • 卓越资讯
  • 猜你想看
  • 常见问题

    Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。[详细课程]

    软件开发是根据用户要求建造出软件系统或者系统中的软件部分的过程;软件开发是一项包括需求捕捉、需求分析、设计、实现和测试的系统工程。[详细课程]

    软件测试是在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。[详细课程]

    Python是一种面向对象的解释型计算机程序设计语言,语法简洁清晰,特色之一是强制用空白符作为语句缩进,它常被昵称为胶水语言,能够把用其他语言制作的各种模块。[详细课程]

    UI设计分为实体UI和虚拟UI,互联网说的UI设计是虚拟UI,一般是指对软件的人机交互、操作逻辑、界面美观的整体设计。[详细课程]

    大数据,又称巨量资料,指的是所涉及的数据资料量规模巨大到无法通过人脑甚至主流软件工具,在合理时间内达到撷取、管理、处理、并整理成为帮助企业经营决策更积极目的的资讯。[详细课程]

    云计算是一种按使用量付费的模式,这种模式提供可用的、便捷的、按需的网络访问, 进入可配置的计算资源共享池(资源包括网络,服务器,存储,应用软件,服务),这些资源能够被快速提供,只需投入很少的管理工作,或与服务供应商进行很少的交互。[详细课程]

    西安市长安北路8号高速大厦三楼

    电话:029-61876930