Java程序性能优化——设计优化

原文出自:http://blog.csdn.net/anxpp/article/details/51914119,转载请注明出处,谢谢!

1、前言

OK,之前写了一篇文章:“23种设计模式介绍以及在Java中的应用”详细介绍了如何将设计模式应用到Java编程中,而本文旨在介绍如何利用他们优化我们的程序,使其性能更佳。

设计模式的详细介绍请参照上面链接中的文章,不是本文的重点。

而Java程序的性能优化,不一定就仅仅是以提高系统性能为目的的,还可能是以用户体验、系统可维护性等为目的。

2、概述

我们知道,设计模式能够大大的优化我们的代码,是针对某一类问题的最优解决方案,是从许多优秀的软件系统中总结出的。

本文重点是Java程序性能优化中的设计优化,介绍的设计模式都是与性能相关的。

出了设计模式,文章也会介绍一些相关的设计组件和设计方法。

3、合理使用设计模式

该节中涉及的设计模式,都在文首链接的文章中详细的介绍了,如果不清楚他们的实现,请先阅读它们。

3.1、单例模式

单例模式最容易理解,也最常见,是一种对象创建模式。

下面是一种简单但正确的实现方式:

  1. public enum EasySingleton{
  2. INSTANCE;
  3. }

上面的方式实现代理,利用的是Java自有的机制,线程是安全的,也不担心被使用反射强行调用构造方式产生多个实例。

在Java语言中,单例模式能明显带来的好处:

1、对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级的对象来说,尤为明显。

2、由于没有new更多的对象,内存使用频率也降低,从而减轻GC(垃圾回收器)的压力。

不过单例模式切不可滥用,不然很容易造成内存泄露,可参考:JAVA 内存泄露详解

3.2、代理模式

代理模式也很常用,可以屏蔽用户对真实对象的访问。

而且代理模式还能简单的实现AOP(面向切面编程)。

但是涉及到性能的,主要是体现在使用代理模式实现延迟加载。延迟加载的核心思想是:如果当前没有使用这个对象(或组件),就不需要真正的创建它。

3.2.1、简单示例

下面还是要看一个简单的示例:

  1. package com.anxpp.hello911.proxy;
  2. //使用
  3. public class SimpleProxy {
  4. public static void main(String[] args) {
  5. IBase base = new BaseProxy(); //使用代理
  6. base.doSomeThing(); //使用时懒加载
  7. }
  8. }
  9. interface IBase{
  10. String doSomeThing();
  11. }
  12. //类本身,通常是重量级的对象
  13. class Base implements IBase{
  14. public Base() {
  15. try {
  16. //构造这个对象可能是非常耗时的操作
  17. Thread.sleep(2000);
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. @Override
  23. public String doSomeThing() {
  24. return "result";
  25. }
  26. }
  27. //代理类
  28. class BaseProxy implements IBase{
  29. private IBase base = null;
  30. @Override
  31. public String doSomeThing() {
  32. if(base==null)
  33. base = new Base();
  34. return base.doSomeThing();
  35. }
  36. }

当我们要使用的对象是一个相对重量级的时候,我们可以使用上面的代理模式,为这个对象作懒加载。

为什么会优化性能呢?这是对用户而言,因为对象是懒加载的,比如,系统启动速度会有效(基于这个对象的构造复杂度)提升,因此会很好的改善用户的体验。再者,有些组件,可能再程序的生命周期并不一定会被调用,而使用懒加载,无疑就避免了这些资源的浪费。

3.2.2、动态代理

动态代理是在运行时,动态的生成代理类。

如果类本身实现的接口中包含了较多的方法,那么,为每个接口都实现一个代理类,是比较繁琐的。 如果接口发生改变,真是对象和代理对象都要修改。但是若使用代理模式生成方法,将大大优化上面出现的问题。

3.3、享元模式

享元模式的主要目的就是提高系统性能,就是真正意思上的性能优化了。

享元模式的最佳实践之一,就是Java中的String类了,相信大家也是非常清楚的。

其核心原理:如果系统中存在多个相同的对象,那么只需要共享一分对象的拷贝。

对性能的提升主要体现在两点:

1、节约重复创建对象的开销。

2、减小系统内存的开销。

3.4、装饰者模式

装饰者模式巧妙的设计结构:可以动态的为对象添加功能。

根据“合成/聚合”复用原则,代码复用应该尽可能使用委托(即组合),而不是继承,因为继承是一种紧耦合的,父类的任何改动都会影响其子类,不利于系统维护。但是委托使松耦合的,只要接口不变,委托类的改动并不会影响其上层对象。

装饰者模式可以有效的分离性能组件和功能组件,从而提升模块的可维护性并增加模块的复用性。

具体实现请参考文首的文章链接中的相关内容。

3.5、观察者模式

观察者模式也是一种比较常用的设计模式。

系统中的一个对象的行为依赖另一个对象时,观察者模式就相当有用。

如果在常规方法中,需要实现类似功能的话,需要开启多个线程监控所依赖的对象的状态(多线程实际上是会加重系统的负担的),但是入股欧使用观察者模式,实现这样的功能可以在单线程中完成。

观察者模式可以用于时间的监听、通知发布等场合,可以确保将这个变化通知给观察者。

JDK中也实现了一套观察者模式,详见文首链接的文章。

3.6、Value Object模式

Value Object是一种什么样的模式呢?其实就是将一组操作原子化。

比如,如果我们要从数据库取得一组特定的结果,他们可能需要经过多次查询或者还需要计算,那么如果仅仅是在Java代码中经过多次查询并组织成我们的目标结果,可能并不是一个好的设计。相反,我们可以将这些属性,封装到一个对象中,然后使用存储过程(Oracle也直接导入Java代码来代替存储过程,如果数据需要经过大量的计算处理,这将比存储过程效率高很多)将这些操作原子化,大大减少数据库访问次数,就能达到系统优化的目的。

而这种模式的应用不仅仅上上面这点,比如我们前端访问服务器取得数据,需要经过多次取值再组合显示的话,我们完全可以将这些属性封装到一个对象中,同意处理后返回,会减少服务器访问次数(不过如果需要懒加载,就需要分步获取数据)。

3.7、业务代理模式

业务代理模式可能概念上有点近似Value Object模式,不过它封装的不是一系列操作的属性,而是将部分业务流程组合到一起。

我们也可以将其与模板方法做对比,他们都是将一系列操作组合到一起。

业务代理模式将一些业务流程封装在前台系统,为系统性能优化提供了基础平台。

4、组件和方法

4.1、缓冲(Buffer)

缓冲区是一块专门用于化解程序中各个模块(或者层次)间的性能差异的,可以提高系统性能。

使用的地方也很多,比如我们要将接收到的数据保存到硬盘中,从网络I/O中读取的数据是不稳定的,可能会很快,但是写入数据到硬盘的速度基本是固定的,两者是有差异的。我们可以通过在内存中开辟一块用来缓存数据,然后按一定的机制统一写到硬盘中,以协调两者的速度不匹配问题。这时候,如果从网络来的数据比较集中,也不用等数据都写入带硬盘后再继续接收剩余的数据,相反,如果网络I/O的数据很少,也可以先放到缓冲中,等到数据量达到一定程度后再统一写入硬盘。

缓冲可以协调上层组件和下层组件的性能差异。当上层组件性能优于下层组件时,可以有效减少上层组件对下层组件的等待时间。

由于I/O操作很容易成为性能瓶颈,所以尽可能在I/O读写中加入缓冲组件,以提高性能。

4.2、缓存(Cache)

缓存也是一块内存中专门开启的空间,主要是缓存数据处理结果,并提供给下一次访问。

比如我们查询数据库的结果,如果没有修改数据库中的数据,那么每次查询的结果应该是一样的,我们没必要就每次要去查询一次,直接将结果缓存到内存中,下次需要的时候直接从内存中取即可。

缓存的使用场合非常多,所以现在也有很多流行的支持缓存的NoSQL数据库,比如Redis。

目前也有很多缓存使用相关的框架,不仅可以缓存数据到本地,还可以缓存到远程分布式缓存服务器中。

缓存可以保存一下来之不易的数据或计算结果。当需要再次使用这些数据时,可以从缓存中低成本的获取。

4.3、池

对象池化也是一个非常常用的系统优化技术。

核心思想是:如果一个类被频繁请求使用,那么不必每次都生成一个示例,可以将这个类的一些实例保存在一个“池”中,待需要使用时,直接从池中获取。

实现上,它可以是数组、链表等任何集合。

可能使用最多的就是线程池,线程池中保存的就是可以被重用的线程对象,当任务呗提交到线程池时,系统并不一定需要新建线程,而是从池中获取一个可用的线程来执行这个任务。

在程序中使用数据库连接池和线程池,可以有效的改善系统咋高并发下的性能。而目前可能对数据库操作都常使用一些ORM框架,它们都很好的封装了数据库连接池,可能碰到更多的,还是线程池。当然,其他类似的情况,我们也可以考虑自己实现一个池。

4.4、并行而不是串行

也就是多线程技术,它可以将CPU的潜能发挥到最大化。

并发相关技术请参考博客总并发相关的文章。

4.5、负载均衡

对于一些大型应用,单台服务器是无法满足需求的,可能就需要部署多台作集群,然后使用负载均衡技术将工作尽可能的平均分配到各个服务器上。

比如一个Web服务器,如果较高的并发已经导致系统频繁的无响应等,通常就会配置多台服务器集群,然后使用Nginx等应用作负载均衡,将请求分配到不同的服务器上。而Session的管理,可能就会使用诸如Redis等缓存数据库,统一管理。

4.6、时间与空间之间的权衡

对于不同的业务类型,可能对时间(CPU)和空间(存储)的需求也各不相同。

性能的优化在于掌握各部分组件的性能平衡点。如果系统CPU资源有空闲,但是内存使用紧张,便可以考虑使用时间换空间的策略,大道整体性能的改进。相反,如果CPU资源紧张,就可以考虑用空间换时间。

在很多算法(比如常见的排序算法),他们对的时间复杂度和空间复杂度是各不相同的,在使用时没应考虑时间和空间的权衡。

5、总结

本文主要是探讨在设计上如何优化我们的程序,而优化并不一定就完全是提高系统的性能,还可能是用户体验、可维护性等。

时间: 2024-08-02 06:50:52

Java程序性能优化——设计优化的相关文章

《Java程序性能优化》学习笔记 Ⅰ设计优化

豆瓣读书:http://book.douban.com/subject/19969386/ 第一章 Java性能调优概述 1.性能的参考指标 执行时间: CPU时间: 内存分配: 磁盘吞吐量: 网络吞吐量: 响应时间: 2.木桶定律   系统的最终性能取决于系统中性能表现最差的组件,例如window系统内置的评分就是选取最低分.可能成为系统瓶颈的计算资源如,磁盘I/O,异常,数据库,锁竞争,内存等. 性能优化的几个方面,如设计优化,Java程序优化,并行程序开发及优化,JVM调优,Java性能调

Java程序性能优化——性能调优层次

为了提升系统性能,开发人员可以从系统的各个角度和层次对系统进行优化.除了最常见的代码优化外,在软件架构上.JVM虚拟机层.数据库以及操作系统层都可以通过各种手段进行调优,从而在整体上提升系统的性能. 设计调优 设计调优处于所有调优手段的上层,它往往需要在软件开发之前进行.在软件开发之初,软件架构师就应该评估系统可能存在的各种潜在的问题,并给出合理的设计方案.由于软件设计和架构对软件整体有决定性的影响,所以,设计调优对系统性能的影响也是最大的.如果说,代码优化.JVM优化都是对系统微观层面上"量&

[JAVA] java程序性能优化

一.避免在循环条件中使用复杂表达式 在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快. 例子: import java.util.vector; class cel { void method (vector vector) { for (int i = 0; i < vector.size (); i++) // violation ; // ... } } 更正: class cel_fixed { void metho

Java程序性能优化技巧

多线程.集合.网络编程.内存优化.缓冲..spring.设计模式.软件工程.编程思想 1.生成对象时,合理分配空间和大小new ArrayList(100); 2.优化for循环Vector vect = new Vector(1000);for( inti=0; i<vect.size(); i++){ ...}for循环部分改写成:int size = vect.size();for( int i=0; i>size; i++){ ...} 如果size=1000,就可以减少1000次si

Java程序性能优化:代码优化

现在计算机的处理性能越来越好,加上JDK升级对一些代码的优化,在代码层针对一些细节进行调整可能看不到性能的明显提升, 但是我觉得在开发中注意这些,更多的是可以保持一种性能优先的意识,对一些敲代码时间比较短的同学挺有意义的. 一 循环条件下,循环体和判断条件中,都要避免对使用复杂表达式,减少对变量的重复计算 1.在循环中应该避免使用复杂的表达式. 在循环中,循环条件会被反复计算,应该避免把一些计算放在循环进行的部分中,程序将会运行的更快.比如: for(int i=0;i<list.size();

《Java程序性能优化:让你的Java程序更快、更稳定》

Java程序性能优化:让你的Java程序更快.更稳定, 卓越网更便宜,不错的书吧

Java程序性能优化——性能指标

性能概述 为什么程序总是那么慢?它现在到底在干什么?时间都花到哪里去了?也许,你经常会抱怨这些问题.如果是这样,那说明你的程序出了性能问题.和功能性问题相比,性能问题在有些情况下,可能并不算什么太大的问题,将就一下,就过去了!但是,严重的性能问题会导致程序瘫痪.假死.直至崩溃.本节就先来认识性能的各种表现和指标. 看懂程序的性能 读客户端程序而言,拙劣的性能会严重影响用户体验:界面停顿.抖动(非动作特效).响应迟钝等问题会遭到用户不停的抱怨.一个典型的例子就是Eclipse IDE工具在Full

《Java程序性能优化》学习笔记 Ⅳ JVM调优

第五章 JVM调优5.1 Java虚拟机内存模型1.JVM虚拟机将其内存数据分为程序计数器.虚拟机栈,本地方法栈,Java堆,和方法去等部分.5.2 JVM内存分配参数5.3 垃圾收集基础5.4 常用调优案例和方法5.5 使用JVM参数5.6 实战JVM调优 <Java程序性能优化>学习笔记 Ⅳ JVM调优

Java程序性能优化-概述

前言 这两天在看<Java程序性能优化>这本书,将我学到的书上好的东西分享给大家.做过开发的人应该或多或少都碰到过性能问题,遇到性能问题你是怎么做的呢?你能看懂程序的性能吗?本篇给大家讲下如何看懂程序的性能及性能的参考指标. 正题 程序性能的表现方式: 1.执行速度:程序的反映是否迅速,响应时间是否足够短. 执行速度可以受到多方面的影响,比如逻辑写的有问题,查询数据量大,网络问题等等. 2.内存分配:内存分配是否合理,是否过多地消耗内存或者存在泄漏. 要根据程序的运行情况及服务器内存大小合理分