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

2318人阅读 评论(0) 收藏 举报
分类:

原文出自: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、总结

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

查看评论

《Java程序性能优化 让你的Java程序更快、更稳定》阅读笔记

java性能调优部分 Linux中常用的监控CPU整体性能的工具有: § mpstat: mpstat 不但能查看所有CPU的平均信息,还能查看指定CPU的信息。               ...
  • JiShuiSanQianLi
  • JiShuiSanQianLi
  • 2016-11-09 10:05:29
  • 1673

Java程序性能优化——让你的Java程序更快、更稳定.pdf

  • 2017年10月07日 15:22
  • 5.14MB
  • 下载

JAVA程序性能调优(一)

性能调优官网理论:https://docs.oracle.com/cd/E19900-01/819-4742/abeik/index.html heap size xms=G1 eden space...
  • hubanbei2010
  • hubanbei2010
  • 2017-12-07 15:06:08
  • 151

Java程序性能优化 让你的Java程序更快、更稳定.pdf

  • 2015年09月27日 16:34
  • 110.32MB
  • 下载

《Java程序性能优化:让你的Java程序更快、更稳定》高清完整扫描PDF版

  • 2013年12月14日 17:36
  • 110.32MB
  • 下载

JAVA程序性能优化

一、避免在循环条件中使用复杂表达式 在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。 例子: impor...
  • chow__zh
  • chow__zh
  • 2016-04-10 12:50:48
  • 1349

JAVA程序性能优化(真的很重要,要么速度慢死了)

Java程序性能优化 一、避免在循环条件中使用复杂表达式 在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。 ...
  • ABC006250
  • ABC006250
  • 2012-03-31 17:20:01
  • 7563

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

为了提升系统性能,开发人员可以从系统的各个角度和层次对系统进行优化。除了最常见的代码优化外,在软件架构上、JVM虚拟机层、数据库以及操作系统层都可以通过各种手段进行调优,从而在整体上提升系统的性能。设...
  • ma_hoking
  • ma_hoking
  • 2015-04-23 22:04:44
  • 1506

常用优化组件和方法- Java程序性能优化--让你的Java程序更快、更稳定

2.2  常用优化组件和方法 本节主要介绍可用于系统性能优化的组件和性能优化思想,重点介绍缓冲和缓存这两个组件以及它们的使用方法。此外,还将介绍几种常用的优化思想,如池化对象、并行代替串行、负载...
  • zxsted
  • zxsted
  • 2013-11-25 23:43:01
  • 875

《<em>Java程序性能优化</em>:让你的Java程序更快、更稳定》高清完...

<em>JAVA程序性能优化</em>-让你的java程序更快、更稳定学习笔记... <em>Java程序性能优化</em>- 让你的Java程序更快、更稳定pdf 《<em>Java程序性能优化</em> 让你的Java程序更快、更稳...
  • 2018年04月17日 00:00
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 88万+
    积分: 5832
    排名: 5509
    博客专栏
    music