浅谈Java API中基本数据类型包装类的缓存设计

来源:互联网 发布:行知实验幼儿园 编辑:程序博客网 时间:2024/05/01 18:45

缓冲在计算机中的作用

    缓存的英文含义是“safekeeping  storage”,顾名思义就是一块可以安全使用的存储空间。那么既然计算机中已经有了硬盘和内存这些存储空间,为什么还需要缓存的存在。

    首先,缓存的原始意义是指访问速度比RAM快的一种RAM,使用的是SRAM技术(价格比较昂贵),最初用在计算机的硬件中用来缓解cpu和内存之间的速度差异。我们都知道著名的“二八定律”:即任何东西,最重要的只占其中一小部分,约20%,其余80%的都是次要的。那么同样cpu主要访问内存中20%的数据,为了不致每次处理那20%的数据都需要去读取速度相对缓慢的内存,就设计了高速缓存用于保存那经常处理的20%数据来提高cpu的处理速度。同时在设计过程中还需要注意的是如何确定那些数据放在高速缓存中,这当中有很多策略可以选择。譬如:最久未使用算法、先进先出算法、最近最少使用算法、非最近使用算法等。这些策略的重要目的是不仅缓存刚刚处理过的数据,还要尽可能的把将要使用的数据预先从内存中读取到高速缓冲中。

    然而随着技术的发展和计算机用户的不断增多,不仅在计算机硬件中存在设备速度不同步,同时在各种基于服务器数据服务的应用中也存在客户端(包括浏览器,移动APP等)和服务器速度不同步的情况。为了缓解目前普通用户的高性能PC和移动终端对服务器能够快速响应和返回结果的需求,现在普遍采用用于缓解硬件速度的cache技术。主要实现方法是对用户经常访问的20%数据建立一个高速缓存,使的不用对用户的每次访问都去访问数据库而使用缓存。现在主要存在的有服务器缓存和本地缓存。


Java API中的缓存代码

    不仅在硬件技术和大型应用的构建中能够使用到缓存技术,在平常的代码中也能够通过使用缓存技术来提高程序的运行效率。在Java的API中就使用了这种技术来提高程序的运行效率。

    Java中提供了基本数据类型包装类和一些列相关方法来对基本数据类型进行操作。

    下面展示了通过一个基本数据类型来获得它的包装类的方法。

    Character a=Character.valueOf('a');
    通过Character的静态方法可以快速获得一个基本类型数据的包装类。然而当我们深究这个代码实现的时候,就能够发现一个技巧。

  public static Character valueOf(char c) {        if (c <= 127) { // must cache            return CharacterCache.cache[(int)c];        }        return new Character(c);    }    

可以看到,对于字符的ASCII码小于等于127的情况,使用的是CharacterCache类的cache数组字段进行返回一个Character类。而大于127的情况,则new一个Character。这充分体现了二八定律,因为开发者最常使用的字符都集中在0~127的ASCII字符。
通过增加一个cache系统,就可以直接获得一个已经cached的包装类而省去new的过程,这样就可以减少构建类的时间,提高程序运行效率。虽然这样的设计并不能显著的提高程序的性能,但是可以通过这个思路帮助我们构建更加大型更加高效的应用。

下面是CharacterCache实现代码:

 private static class CharacterCache {        private CharacterCache(){}        static final Character cache[] = new Character[127 + 1];        static {            for (int i = 0; i < cache.length; i++)                cache[i] = new Character((char)i);        }    }

上述代码使用了单例模式,通过私有构造方法限制了类的构造同时提供唯一的类的实例供使用。(具体介绍参见GoF的设计模式)


常见的缓存框架

    在实际的构建应用中,并不需要自己构建一个cache系统。有很多比较成熟的cache系统,譬如Memcache,Ehcache,OSCache,Java Caching System,SwarmCache等,这些cache系统基本上都支持分布式和集群,能够极大地提高应用的性能。

原创粉丝点击