Java常用缓存组件和方法

在我们系统开发中,有许多关于性能提升方面的组件,这里介绍并总结一下;

缓冲(Buffer)

缓冲区是一块特定的内存区域。开辟缓冲区的目的是通过缓解应用程序上下层之间的差异,提高系统的性能。在日常生活中,缓冲的一个典型应用是漏斗;


漏斗,相当于缓冲区,漏斗口很大,可以及时处理上面倒出的水,这就意味着上层系统效率很高,下层系统效率很低,,因为瓶口很细,无法及时将水倒入瓶中;我感觉漏斗也像是一种模式,适配器模式,假设有一个水壶的口很大,而瓶子的口很小,这个时候就需要一个适配器漏斗了,他能把两端桥接起来,使得他们能够进行传输;

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

基于这样的结构,上层应用组件不需要等待下层组件真实的接受全部数据,即可返回操作,加快了上层组件的处理速度,从而提升系统的整体性能。

缓冲最常用的场景就是提高I/O的速度。JDK内不少组件都提供了缓冲功能,一般名字里面都会带Buff。

Writer writer=new BufferedWriter(new FileWriter("C:\\E盘\\teacher.java"));
IO使用的主要设计模式使装饰者模式,这里来看一看源码

  public BufferedWriter(Writer out, int sz) {
        super(out);
        if (sz <= 0)
            throw new IllegalArgumentException("Buffer size <= 0");
        this.out = out;
        cb = new char[sz];
        nChars = sz;
        nextChar = 0;

        lineSeparator = java.security.AccessController.doPrivileged(
            new sun.security.action.GetPropertyAction("line.separator"));
    }
 private static int defaultCharBufferSize = 8192;

其内部是创建了一个8192大小的字符串缓冲区;

一般来说,缓冲区不宜过小,过小的缓冲区无法起到真正的缓冲作用,缓冲区也不宜过大,过的的缓冲区会浪费系统内存,增加GC负担。

缓存(Cache)

缓存也是一块为提升系统性能而开辟的内存空间,缓存的主要作用是暂存数据处理结构,并提供下次访问使用,频繁的访问数据库会耗费CPU资源也会使数据库的性能降低,缓存的作用就是讲这些数据暂时存储起来,当有其他线程或者客户端需要查询相同的数据资源时,可以省略对这些数据的处理流程,而直接从缓存中获取处理结果,bong立即返回给请求组件,以此提高系统的相应时间。

缓存的使用非常普遍,比如,目前流行的几种浏览器都会在本地缓存远程的页面,从而减少远程HTTP访问次数,加快网页的加载速度,又比如,在服务端的系统开发中,设计人员可以为一些核心API加上缓存,从而提高系统的整体性能。

最为简单的缓存可以直接使用HashMap实现,当然,这样会有很多问题,比如上面时候该清理无效的数据,如何防止缓存数据过多而导致的内存溢出等,现在市面上有很多缓存,自己常用的有EhCache,memcache等。

对象复用池

对象池化,是目前非常常用的一种系统优化技术,它的核心思想是,如果一个类被频繁的请求使用,那么不必每次都生成一个实例,可以将这个类的一些实例保存在一个池中,待需要使用的时候直接从池中获取。这个“池”就被称为对象池。在实现细节上,它可能是一个数组,一个链表或者任何集合类。

对象池的使用非常广泛,比较常用的就是线程池和数据库连接池。线程池中,保存着可以被重用的线程对象,当有任务被提交到线程池,系统并不需要新建线程,而是从池中获得一个可用的线程,执行这个任务,在任务结束后,也不关闭线程,而将它返回到池中,以便下次继续使用。由于线程的创建和销毁是较为费时的工作,因此,在线程调度频繁的系统中,线程池可以很好地改变性能。

数据库连接池也是一种特殊的对象池,它用于维护数据库连接的集合。当系统需要访问数据库时,不需要重新建立数据库连接,而可以直接从池中获取;在数据库操作完成后,也不关闭数据库连接,而是将连接返回到连接池中。由于数据库连接的创建和销毁是重量级的操作,因此,避免频繁进行这两个操作,对改善系统的性能也有积极意义。

目前应用较为广泛的数据库连接池组件有C3P0和Proxool。其中C3P0是伴随着Hibernate一起发布,与hibernate联系紧密的数据库连接池。

除了这两个,对于普通的JAVA对象,在必要的时候,也可以进行池化管理,对于那些经常使用,并且创建很费时的大型对象来说,使用对象池维护,不仅可以节省获得对象实例的成本,还尅减轻GC频繁回收这些对象产生的系统压力;

并行替代串行

能够使用多线程的尽量使用多线程去处理;

负载均衡

对大型应用来说,系统负载可能非常重。这个时候就要使用负载均衡了。

一个典型的实现便是Tomcat集群。配置Tomcat集群实现负载均衡,可以通过Apache服务器实现,即,使用Apache服务器作为负载分配器,将请求转向各个Tomcat服务器,从而实现负载均衡。

时间换空间

由于系统资源是有限的,为了在有限的资源内,达成某些特定的性能目标,就需要使用时间换空间或者空间换时间的方法。

时间换空间通常用于嵌入式设备,或者内存,硬盘不足的情况,通过使用牺牲CPU的方式,换的原本需要更多内存或者磁盘空间才能完成的工资。

下例是一个非常简单的时间换空间的 算法,实现了a,b两个变量的值交互,交换两个变量最常用的方法是使用一个中间变量,而引入额外的变量则需要更多的空间,采用下面的方法,则可以免去中间变量,而达到变量交互的目的,其代价是花费了更多的时间

a=a+b;
b=a-b;
a=a-b;

空间换时间

与时间换空间的方法相反,空间换时间则是采用更多的内存或者磁盘空间换取CPU资源或者网络资源等,通过增加系统的内存消耗,来加快程序的运行速递。

这个方法最常用的就是缓存,缓存就是一块内存区域,

上面简单的介绍了几个常用的缓存组件,以后会详细的去分析这些东西来对java程序性能进行优化;



已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 成长之路 设计师:Amelia_0503 返回首页