java性能优化笔记 - 01
来源:互联网 发布:windows 适合的Ps 编辑:程序博客网 时间:2024/05/29 17:49
★为了提高系统的速度,仅增加CPU处理器的数量并不一定能起到有效地作用,需要从
根本上修改程序的串行行为,提高系统内科并行化的模块比重。在此基础上,合理增加并
行处理器的数量,才能从最小的投入得到最大的加速比。
1. 设计模式
使用设计模式可以有效的避免时间和空间上的开销,但不能过渡设计。
★代理模式
因为静态内部类在调用时才会被加载,故使用代理模式可以延迟加载,提高系统性能。
如Hibernate中取得对象的load()方法就采取了这种策略。
★享元模式
通过同一个工厂创造出不同的产品,从而在一定程度上节省了内存空间。与连接池等区
别是,连接池创建的是同一对象。
★装饰器模式
通过装饰器,可以提高类的聚合能力。如BufferedOutputStream类,在OutputStream的
基础上增加了缓冲区,减少了IO的访问次数,提高了系统性能。
★观察者模式
形如JDK中的JButton监听事件,只要设置触发动作和响应事件。一旦动作触发即可并监
听到。
★Value Object
网络传输对象,减少因为属性获取而导致的网络传输次数。
★业务代理
将一些业务流程封装在前台系统,为系统性能优化提供了基础平台。在业务代理中,不仅
可以复用业务流程,还可以视情况为展示层组件提供缓存等功能,从而减少远程方法调用
次数,降低系统压力。
2.缓冲
缓冲可以协调上层组件和下层组件的性能差。当上层组件性能优于下层组件时,可以有效
减少上层组件对下层组件的等待时间。基于这样的结构,上层应用不需要等待下层组件真
实地接受全部数据,即可返回操作,加快了上层组件的处理速度,从而提高系统的整体性
能。
★由于I/O操作很容易成为性能的瓶颈,尽可能在I/O读写中加入缓冲组件以提高系统的性
能。使用动态代理无需修改一个逻辑方法的代码,便可以为它加上缓存功能,提高其性能。
3.对象复用“池”
在程序中使用数据库连接池和线程池,可以有效的改善系统在高并发下的性能。只有对重
量级对象使用对象池技术才能提高系统性能。对轻量级的对象使用对象池,可能反而会降
低系统性能。
4.负载均衡
在使用tomcat集群时,有两种基本的session共享模式。
★黏性session模式:所有的session信息被平均分配到各个tomcat节点。但一个节点宕机,
它所维护的session信息将丢失,不具备高可用性。且一台用户只能与一台tomcat交互,因
为其它tomcat节点上不保存这个用户信息。
★复制session模式:将所有session在所有的tomcat节点上保持一致。当一个节点的session
信息被修改,这个session会被广播到其它tomcat节点上以保持session同步。很容易引起网路
繁忙,影响系统效率。
5.String对象
不变性:不变模式的主要作用在于当一个对象需要被多线程共享,并且访问频繁时,可以省略同
步和锁等待的时间,从而大幅度提高系统性能。
针对常量池的优化:当两个String对象拥有相同的值时,它们只引用常量池中的同一个拷贝。当
同一个字符串反复出现时,可以大幅度节省内存空间。
subString()方法的内存泄露:在使用该函数时,采用空间换时间的手段,会重新new一个string
对象。应用程序无法使用它,因此在实际应用中,不用担心它所带来的麻烦。但是,java.lang包
内的对象对它的调用会引起内存泄露。
对于静态字符串的连接操作,java在编译时会进行彻底的优化,将多个连接操作的字符串在编译
时合成一个单独的长字符串。因此一些看起来很慢的代码,可能实际上并不会太慢。
例如:
String s = str1 + str2 + str3;
在编译时会转为 new StringBuilder(String.valueOf(str1)).append(str2).append(str3);
StringBuffer --------> 线程同步,需消耗大量资源。
StringBuilder-------> 线程不同步,效率更高。
如果能预先评估以上的大小,将能够有效地节省扩容等操作,从而提高系统的性能。在集合
ArrayList的扩容中同样适用。
当转化成字符串的时候,应当避免使用""串进行转化。使用合适的String.valueOf方法或者包装类的toString(value)方法。
尽量使用StringBuilder进行字符串拼接。
使用Java 6 update 20引入的-XX:+OptimizeStringConcat选项来提高字符串拼接的性能。
6.ArrayList与LinkedList
①ArrayList存在扩容,LinkedList不存在扩容等性能开销。
②ArrayList适合在结尾处添加删除元素,不适合任意位置。因为其每次添加删除元素时需重
新调整整个宿主,性能开销较大。
③在LinkedList的实现中,首先要通过循环找到要删除的元素。如果要删除的位置位于List的
前半段,则从前进行查找,反之亦然。但要移除List中间的元素,却几乎要遍历完半个List,在
List拥有大量元素的情况下,效率很低。
对ArrayList这些基于数组的实现来说,随机访问的速度是很快的。在遍历这些List对象时,可以
优先考虑随机访问。但对于LinkedList等基于链表的实现,随机访问的性能是非常差的,应避免
使用。
编译器将Foreach循环作为迭代器处理,二者是完全等价的。而且在foreach循环的迭代操作中,
又存在一步多余的赋值操作,从而导致Foreach循环的性能比直接使用迭代器略差一点。
7.HashMap
HashMap的高性能需要保证以下两点:
①Hash算法必须是高效的。
②Hash值到内存地址(数组索引)算法是快速的,可根据内存地址直接取得。
HashMap的扩容操作会遍历整个HashMap,应该尽量避免该操作的发生。设置合理的初始大小和
负载因子,可以有效地减少HashMap扩容的次数。
HashMap的性能在一定程度上取决于hashCode()的实现,一个好的hashCode()算法,可以尽可能
减少冲突,从而提高HashMap访问速度。
LinkedHashMap可以简单的理解为一个维护了元素次序表的HashMap
不要再迭代器模式中修改被迭代的集合。如果这么做,就会抛出ConcurrentModificationException异常,
这个特性适用于所有的集合类,包括HashMap,Vector,ArrayList等。
虽然一般认为get()方法是只读的,但是当前的LinkedHashMap却工作在按照元素访问顺序排序的模式中,
get()方法会修改LinkedHashMap中的链表结构,以便将最近访问的元素放置到链表的末层。当LinkedHashMap
工作在这种模式时,不能在迭代器中使用get()操作。
TreeMap:TreeMap排序方式和LinkedHashMap是不同的,LinkedHashMap是基于元素进入集合的顺序或被访问
的先后顺序排序。而TreeMap则是基于元素的固定顺序(由Comparator或者Comparable确定)
为了确定Key的排序算法,可以使用两种方式
①在TreeMap的构造函数中注入一个Comparator
public TreeMap(Comparator <? super K > comparator)
②使用一个实现Comparable接口的Key。
8.Set
所有Set的实现,都只是对应的Map的一种封装而已。
HashSet -----------> HashMap 输出顺序毫无规律
LinkedHashSet ----------> LinkedHashMap 输出顺序与输入顺序完全一致
TreeSet ----------> TreeMap 输出顺序从小到大或者从大到小
9.优化集合访问代码
①分离循环中被重复调用的代码。
②省略相同的操作。
③如果可以,则尽量直接访问内部元素而不要调用对应的接口。函数调用是需要消耗系统资源的,直接访问会更
高效。
10.RandomAccess接口
主要是标示那些可支持快速随机访问的List实现。在JDK中,任何一个基于数组的List实现都实现了RandomAccess
接口,而基于链表的实现则都没有。因为只有数组能够进行快速的随机访问,而对链表的随机访问需要进行链表的遍历。
通过RandomAccess可以知道List是否支持快速随机访问。如果应用程序需要通过索引下标对List做随机访问,尽量
不要使用LinkedList。
- java性能优化笔记 - 01
- java性能优化笔记 java程序优化
- java性能优化笔记 - 02
- java性能优化笔记 - 03
- 《Java程序性能优化》-笔记
- 笔记:Java程序性能优化
- 《Java程序性能优化》-笔记
- 笔记 :java性能优化 (from-JAVA程序性能优化)
- java程序性能优化学习笔记day1
- 《Java程序性能优化》第一章笔记
- java性能优化笔记(一)概述
- java性能优化笔记(一)概述
- java性能优化笔记(三)java程序优化
- java性能优化笔记(三)java程序优化
- java性能优化笔记(三)java程序优化
- java性能优化笔记(三)java程序优化
- java性能优化笔记(二)设计优化
- java性能优化笔记(二)设计优化
- label语句
- Qt Windows 下软件 release 发布
- ExtJs自学教程(1):一切从API开始
- 参数个数可变的函数
- ubuntu下新建、编译项目
- java性能优化笔记 - 01
- C语言中的fprintf()函数
- 空的类指针照样调用成员函数
- 线程安全的缓存代码
- 1.1 Application Fundamentals
- ffmpeg 从mp4上提取H264的nalu
- 写给即将进入IT行业的应届生们——谈谈IT岗位
- 有竞争才有进步
- MyEclipse 10.5与ExtJS 4.1.1自动代码提示