阅读更多

最近的机器内存又爆满了,除了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了。

 

下面是参考网络资源总结的一些在Java编程中尽可能要做到的一些地方。

1. 尽量在合适的场合使用单例

使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:
第一,控制资源的使用,通过线程同步来控制资源的并发访问;
第二,控制实例的产生,以达到节约资源的目的;
第三,控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信。

2. 尽量避免随意使用静态变量

要知道,当某个对象被定义为stataic变量所引用,那么gc通常是不会回收这个对象所占有的内存,如

public class A{
static B b = new B();
}
 
此时静态变量b的生命周期与A类同步,如果A类不会卸载,那么b对象会常驻内存,直到程序终止。

3. 尽量避免过多过常的创建Java对象

尽量避免在经常调用的方法,循环中new对象,由于系统不仅要花费时间来创建对象,而且还要花时间对这些对象进行垃圾回收和处理,在我们可以控制的范围内,最大限度的重用对象,最好能用基本的数据类型或数组来替代对象。

4. 尽量使用final修饰符

带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。Java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。

5. 尽量使用局部变量

调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。

6. 尽量处理好包装类型和基本类型两者的使用场所

虽然包装类型和基本类型在使用过程中是可以相互转换,但它们两者所产生的内存区域是完全不同的,基本类型数据产生和处理都在栈中处理,包装类型是对象,是在堆中产生实例。
在集合类对象,有对象方面需要的处理适用包装类型,其他的处理提倡使用基本类型。

7. 慎用synchronized,尽量减小synchronize的方法

都知道,实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。synchronize方法被调用时,直接会把当前对象锁 了,在方法执行完之前其他线程无法调用当前对象的其他方法。所以synchronize的方法尽量小,并且应尽量使用方法同步代替代码块同步。

8. 尽量使用StringBuilder和StringBuffer进行字符串连接

这个就不多讲了。

9. 尽量不要使用finalize方法

实际上,将资源清理放在finalize方法中完成是非常不好的选择,由于GC的工作量很大,尤其是回收Young代内存时,大都会引起应用程序暂停,所以再选择使用finalize方法进行资源清理,会导致GC负担更大,程序运行效率更差。

10. 尽量使用基本数据类型代替对象

String str = "hello";
上面这种方式会创建一个“hello”字符串,而且JVM的字符缓存池还会缓存这个字符串;
String str = new String("hello");
此时程序除创建字符串外,str所引用的String对象底层还包含一个char[]数组,这个char[]数组依次存放了h,e,l,l,o

11. 单线程应尽量使用HashMap、ArrayList

HashTable、Vector等使用了同步机制,降低了性能。

12. 尽量合理的创建HashMap

当你要创建一个比较大的hashMap时,充分利用另一个构造函数
public HashMap(int initialCapacity, float loadFactor)
避免HashMap多次进行了hash重构,扩容是一件很耗费性能的事,在默认中initialCapacity只有16,而loadFactor是 0.75,需要多大的容量,你最好能准确的估计你所需要的最佳大小,同样的Hashtable,Vectors也是一样的道理。

13. 尽量减少对变量的重复计算

for(int i=0;i<list.size();i++)
应该改为
for(int i=0,len=list.size();i<len;i++)
并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。 

14. 尽量避免不必要的创建

A a = new A();
if(i==1){list.add(a);}
应该改为
if(i==1){
A a = new A();
list.add(a);}

15. 尽量在finally块中释放资源

程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。 

16. 尽量使用移位来代替'a/b'的操作

"/"是一个代价很高的操作,使用移位的操作将会更快和更有效
int num = a / 4;
int num = a / 8;
应该改为
int num = a >> 2;
int num = a >> 3;
但注意的是使用移位应添加注释,因为移位操作不直观,比较难理解

17.尽量使用移位来代替'a*b'的操作

同样的,对于'*'操作,使用移位的操作将会更快和更有效
int num = a * 4;
int num = a * 8;
应该改为
int num = a << 2;
int num = a << 3;

18. 尽量确定StringBuffer的容量

StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再 丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。 
如:StringBuffer buffer = new StringBuffer(1000);  

19. 尽量早释放无用对象的引用

大部分时,方法局部引用变量所引用的对象 会随着方法结束而变成垃圾,因此,大部分时候程序无需将局部,引用变量显式设为null。
例如:

Public void test(){
Object obj = new Object();
……
Obj=null;
}
 
上面这个就没必要了,随着方法test()的执行完成,程序中obj引用变量的作用域就结束了。但是如果是改成下面:

Public void test(){
Object obj = new Object();
……
Obj=null;
//执行耗时,耗内存操作;或调用耗时,耗内存的方法
……
}
 
这时候就有必要将obj赋值为null,可以尽早的释放对Object对象的引用。

20. 尽量避免使用二维数组

二维数据占用的内存空间比一维数组多得多,大概10倍以上。

21. 尽量避免使用split

除非是必须的,否则应该避免使用split,split由于支持正则表达式,所以效率比较低,如果是频繁的几十,几百万的调用将会耗费大量资源,如果确实需 要频繁的调用split,可以考虑使用apache的StringUtils.split(string,char),频繁split的可以缓存结果。

22. ArrayList & LinkedList

一 个是线性表,一个是链表,一句话,随机查询尽量使用ArrayList,ArrayList优于LinkedList,LinkedList还要移动指 针,添加删除的操作LinkedList优于ArrayList,ArrayList还要移动数据,不过这是理论性分析,事实未必如此,重要的是理解好2 者得数据结构,对症下药。

23. 尽量使用System.arraycopy ()代替通过来循环复制数组

System.arraycopy() 要比通过循环来复制数组快的多 

24. 尽量缓存经常使用的对象

尽可能将经常使用的对象进行缓存,可以使用数组,或HashMap的容器来进行缓存,但这种方式可能导致系统占用过多的缓存,性能下降,推荐可以使用一些第三方的开源工具,如EhCache,Oscache进行缓存,他们基本都实现了FIFO/FLU等缓存算法。

25. 尽量避免非常大的内存分配

有时候问题不是由当时的堆状态造成的,而是因为分配失败造成的。分配的内存块都必须是连续的,而随着堆越来越满,找到较大的连续块越来越困难。

26. 慎用异常

当创建一个异常时,需要收集一个栈跟踪(stack track),这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照,正是这一部分开销很大。当需要创建一个 Exception 时,JVM 不得不说:先别动,我想就您现在的样子存一份快照,所以暂时停止入栈和出栈操作。栈跟踪不只包含运行时栈中的一两个元素,而是包含这个栈中的每一个元素。
如 果您创建一个 Exception ,就得付出代价。好在捕获异常开销不大,因此可以使用 try-catch 将核心内容包起来。从技术上讲,您甚至可以随意地抛出异常,而不用花费很大的代价。招致性能损失的并不是 throw 操作——尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。真正要花代价的是创建异常。幸运的是,好的编程习惯已教会我们,不应该不管三七二十一就 抛出异常。异常是为异常的情况而设计的,使用时也应该牢记这一原则。

相关回复:
xuanyuan 写道
7.慎用synchronized,尽量减小synchronize的方法
re:同意,不过文中有个地方说错了,使用synchronized关键字并不一定都是锁定当前对象的,要看具体的锁是什么。如果是在方法上加的synchronized,则是以对象本身为锁的,如果是静态方法则锁的粒度是类。
---------------
9.尽量不要使用finalize方法
re:同意,其实不推荐用finalize方法的根本原因在于,JVM的规范并不保证何时执行该方法,所以用这个方法来释放资源很不合适,有可能造成长时间资源得不到释放。
---------------
16.尽量使用移位来代替'a/b'的操作;17.尽量使用移位来代替'a*b'的操作
re:个人不太同意这两条。这样做确实有更好的性能,但是却牺牲了可读性。这两个操作符对很多程序员来说并不直观。我认为在如今硬件价格不那么昂贵的情况下,略微牺牲一些性能,换来更好的可读性和可维护性是好的选择。
 

wuzhengju 写道
19.尽量早释放无用对象的引用
大部分时,方法局部引用变量所引用的对象 会随着方法结束而变成垃圾,因此,大部分时候程序无需将局部,引用变量显式设为null。
例如:
Public void test(){
Object obj = new Object();
……
Obj=null;
}
上面这个就没必要了,随着方法test()的执行完成,程序中obj引用变量的作用域就结束了。但是如果是改成下面:
Public void test(){
Object obj = new Object();
……
Obj=null;
//执行耗时,耗内存操作;或调用耗时,耗内存的方法
……
}
如果Object obj = new Object(); 如果这对象并不是大对象,这有必要吗?Obj=null;只是告诉jvm这个对象已经成为垃圾,至于什么时候回收,还不能确定! 这可读性也不好!
 



相关推荐

  • Java编程中“为了性能”尽量要做的几点

    下面是参考网络资源总结的一些在Java编程中尽可能要做到的一些地方。使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:第一,...

  • java编程中'为了性能'一些尽量做到的地方

    NULL 博文链接:https://mwhgjava.iteye.com/blog/1151072

  • java编程中 为了性能 尽量要做的26点

    JAVA程序性能优化注意事项,好的编程习惯,在实际应用中,非常重要!

  • Java编程中"为了性能"尽量要做到的一些地方

    Java编程中"为了性能"尽量要做到的一些地方

  • [转] Java编程中“为了性能”尽量要做到的一些地方

    下面是参考网络资源总结的一些在Java编程中尽可能要做到的一些地方。1. 尽量在合适的场合使用单例使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要...

  • Java编程中“为了性能”一些尽量做到的地方

    来自: java-t-go - ITeye技术网站 ... ...最近的机器内存又爆满了,出了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的...下面是参考网络资源和总结一些在Java编程中尽可能

  • Java编程中为了"为了性能"尽量要做到的一些地方

    下面是参考网络资源总结的一些在Java编程中尽可能要做到的一些地方。 1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说...

  • 60道关于Redis的常见面试题.pdf

    - 1. 什么是 Redis?它的主要特点是什么? - 2. Redis 支持哪些数据结构?请详细描述每种数据结构的用途和特点。 - 3. 什么是缓存穿透?在使用 Redis 时,如何防止缓存穿透? - 4. 介绍 Redis 的持久化机制以及对比它们之间的区别。 - 5. 如何实现 Redis 的分布式锁?你了解的分布式锁有哪些实现方式? - 6. Redis 的数据淘汰策略有哪些?分别是如何工作的? - 7. 什么是 Redis 事务?它是如何实现的?与传统数据库事务有何不同? - 8. 如何设置 Redis 的主从复制?主从复制有什么优势和限制? - 9. Redis 支持的数据结构中,有哪些可以实现计数功能?请详细说明其使用场景。 - 10. 什么是 Redis Sentinel?它的作用是什么?如何配置和使用 Sentinel?

  • 2024年社交媒体广告行业分析报告.pptx

    2024年社交媒体广告行业分析报告.pptx

  • 网站界面设计mortal0418代码

    网站界面设计mortal0418代码

  • 2024年休闲椅行业分析报告.pptx

    2024年休闲椅行业分析报告.pptx

  • anaconda3 -windows安装的

    anaconda3 -windows安装的

  • 华为客户关系管理策略解析glz.pptx

    华为客户关系管理策略解析glz.pptx

  • asp.net基于三层模式实验室仪器设备管理系统源码.7z

    实验室设备仪器管理系统基于MVC思想和三层设计模式构建,前台采用bootstrap响应式框架,后台运用div+css技术,确保用户界面的友好与兼容性。在Visual Studio 2010或更高版本软件上进行程序开发,利用sqlserver2005或更先进的数据库系统提供稳定的数据支持。 该系统包含四个核心模块:实验室登陆模块、学生模块、教师模块和管理员模块。登陆模块提供用户注册和登陆功能,确保用户信息的准确与安全。学生模块提供实验课仪器设备的信息查询、借领仪器耗材、设备事故的登记等服务,满足学生在实验过程中的各种需求。 管理员模块功能丰富,包括实验室设备信息查询、设备事故记录、设备资料管理、设备损坏管理以及设备耗材借领等。管理员可以方便地查询和统计设备仪器信息,上报和处理设备事故,更新设备操作指南,管理设备损坏信息,以及处理设备耗材的借领和归还。 实验设备管理数据库是系统的核心部分,管理员可以添加、删除、更改设备信息,记录报废、维修、申请购买以及新增设备的详细信息。所有相关信息如报废表、维修表、设备购买申请表、新增设备属性表等都会在终端实时显示,确保信息的及时性和准确性。 此

  • java练习题2.txt

    java练习题

  • 国产达梦数据库DM88.1.1.45下载链接,Linux-rh7-64位版本.zip

    国产达梦数据库DM88.1.1.45下载链接,Linux-rh7-64位版本.zip

  • 物联网嵌入式ESP32开发例程18-FreeRTOS操作系统之任务通知模拟事件标志组C程序代码.rar

    1、嵌入式物联网ESP32项目实战开发。例程经过精心编写,简单好用。 2、代码使用Visual Studio Code + ESP-IDF开发,C语言编程。例程在ESP32-S3上运行。若在其他型号上运行,请自行调整。 3、如果接入其他传感器,请查看发布的其他资料。 4、ESP32与模块的接线,在代码当中均有定义,请自行对照。 5、若硬件差异,请根据自身情况适当调整代码,程序仅供参考。 6、代码有注释说明,请耐心阅读。 7、技术v:349014857;

  • 工作汇报 年终总结2.pptx

    引言 年度工作回顾 系统进展与亮点 技术创新与应用 市场反馈与用户评价 存在问题与挑战 未来展望与计划 结束语与感谢 一、引言 简要介绍智能家居系统的重要性和发展趋势 回顾本年度的工作目标和重点 二、年度工作回顾 系统建设与维护 完成的项目与里程碑 系统稳定性与可靠性提升 团队建设与培训 团队成员构成与职责 培训与技能提升活动 合作伙伴与资源整合 与供应商、合作伙伴的合作情况 资源整合与利用 三、系统进展与亮点 功能扩展与优化 新增功能介绍与效果评估 现有功能的优化与改进 用户体验提升 界面设计与交互优化 用户反馈与改进措施 四、技术创新与应用 物联网技术的应用 传感器与通信技术的升级 大数据分析与应用 智能家居的智能化管理 自动化控制与节能策略 安全防护与预警系统 五、市场反馈与用户评价 市场反馈分析 市场需求与竞争态势 市场占有率与增长趋势 用户评价总结 用户满意度调查结果

  • 基于ssm+vue开发的web新闻流媒体平台源码数据库文档.zip

    基于ssm+vue开发的web新闻流媒体平台源码数据库文档.zip

Global site tag (gtag.js) - Google Analytics