「java实现lfu」Java实现接口

博主:adminadmin 2023-03-18 18:20:10 471

本篇文章给大家谈谈java实现lfu,以及Java实现接口对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

EhCache 分布式缓存/缓存集群

一 缓存系统简介         EhCache 是一个纯 Java 的进程内缓存框架 具有快速 精干等特点 是 Hibernate 中默认的 CacheProvider         EhCache 应用架构图 下图是 EhCache 在应用程序中的位置

         EhCache 的主要特性有         快速 精干         简单         多种缓存策略         缓存数据有两级 内存和磁盘 因此无需担心容量问题         缓存数据会在虚拟机重启的过程中写入磁盘         可以通过 RMI 可插入 API 等方式进行分布式缓存         具有缓存和缓存管理器的侦听接口         支持多缓存管理器实例 以及一个实例的多个缓存区域         提供 Hibernate 的缓存实现         由于 EhCache 是进程中的缓存系统 一旦将应用部署在集群环境中 每一个节点维护各自的缓存数据 当某个节点对缓存数据进行更新 这些更新的数据无法在其它节点 *** 享 这不仅会降低节点运行的效率 而且会导致数据不同步的情况发生 例如某个网站采用 A B 两个节点作为集群部署 当 A 节点的缓存更新后 而 B 节点缓存尚未更新就可能出现用户在浏览页面的时候 一会是更新后的数据 一会是尚未更新的数据 尽管我们也可以通过 Session Sticky 技术来将用户锁定在某个节点上 但对于一些交互性比较强或者是非 Web 方式的系统来说 Session Sticky 显然不太适合         所以就需要用到 EhCache 的集群解决方案         从 版本开始 Ehcache可以使用分布式的缓存了 EhCache 从 版本开始 支持五种集群方案 分别是         ? Terracotta        ? RMI        ? JMS        ? JGroups        ? EhCache Server        其中的三种最为常用集群方式 分别是 RMI JGroups 以及 EhCache Server 本文主要介绍RMI的方式         分布式这个特性是以plugin的方式实现的 Ehcache自带了一些默认的分布式缓存插件实现 这些插件可以满足大部分应用的需要 如果需要使用其他的插件那就需要自己开发了 开发者可以通过查看distribution包里的源代码及JavaDoc来实现它 尽管不是必须的 在使用分布式缓存时理解一些ehcahce的设计思想也是有帮助的 这可以参看分布式缓存设计的页面 以下的部分将展示如何让分布式插件同ehcache一起工作         下面列出的是一些分布式缓存中比较重要的方面         ? 你如何知道集群环境中的其他缓存?        ? 分布式传送的消息是什么形式?        ? 什么情况需要进行复制?增加(Puts) 更新(Updates)或是失效(Expiries)?        ? 采用什么方式进行复制?同步还是异步方式?        为了安装分布式缓存 你需要配置一个PeerProvider 一个CacheManagerPeerListener         它们对于一个CacheManager来说是全局的 每个进行分布式操作的cache都要添加一个cacheEventListener来传送消息

    二 集群缓存概念及其配置         正确的元素类型        只有可序列化的元素可以进行复制 一些操作 比如移除 只需要元素的键值而不用整个元素 在这样的操作中即使元素不是可序列化的但键值是可序列化的也可以被复制         成员发现(Peer Discovery)        Ehcache进行集群的时候有一个cache组的概念 每个cache都是其他cache的一个peer 没有主cache的存在 刚才我们问了一个问题 你如何知道集群环境中的其他缓存?这个问题可以命名为成员发现(Peer Discovery)         Ehcache提供了两种机制用来进行成员发现 就像一辆汽车 手动档和自动档 要使用一个内置的成员发现机制要在ehcache的配置文件中指定cacheManagerPeerProviderFactory元素的class属性为        net sf ehcache distribution RMICacheManagerPeerProviderFactory         自动的成员发现        自动的发现方式用TCP广播机制来确定和维持一个广播组 它只需要一个简单的配置可以自动的在组中添加和移除成员 在集群中也不需要什么优化服务器的知识 这是默认推荐的         成员每秒向群组发送一个 心跳 如果一个成员 秒种都没有发出信号它将被群组移除 如果一个新的成员发送了一个 心跳 它将被添加进群组         任何一个用这个配置安装了复制功能的cache都将被其他的成员发现并标识为可用状态         要设置自动的成员发现 需要指定ehcache配置文件中cacheManagerPeerProviderFactory元素的properties属性 就像下面这样         peerDiscovery=automatic        multicastGroupAddress=multicast address | multicast host name        multicastGroupPort=port        timeToLive= (timeToLive属性详见常见问题部分的描述)        示例        假设你在集群中有两台服务器 你希望同步sampleCache 和sampleCache 每台独立的服务器都要有这样的配置         配置server 和server         cacheManagerPeerProviderFactoryclass= net sf ehcache distribution RMICacheManagerPeerProviderFactory properties= peerDiscovery=automatic multicastGroupAddress= /multicastGroupPort= timeToLive= 手动进行成员发现        进行手动成员配置要知道每个监听器的IP地址和端口 成员不能在运行时动态地添加和移除 在技术上很难使用广播的情况下就可以手动成员发现 例如在集群的服务器之间有一个不能传送广播报文的路由器 你也可以用手动成员发现进行单向的数据复制 只让server 知道server 而server 不知道server         配置手动成员发现 需要指定ehcache配置文件中cacheManagerPeerProviderFactory的properties属性 像下面这样         peerDiscovery=manual rmiUrls=//server:port/cacheName //server:port/cacheName …        rmiUrls配置的是服务器cache peers的列表 注意不要重复配置         示例        假设你在集群中有两台服务器 你要同步sampleCache 和sampleCache 下面是每个服务器需要的配置         配置server         cacheManagerPeerProviderFactoryclass= net sf ehcache distribution RMICacheManagerPeerProviderFactory properties= peerDiscovery=manual /rmiUrls=//server : /sampleCache |//server : /sampleCache         配置server         cacheManagerPeerProviderFactoryclass= net sf ehcache distribution RMICacheManagerPeerProviderFactory properties= peerDiscovery=manual /rmiUrls=//server : /sampleCache |//server : /sampleCache 配置CacheManagerPeerListener        每个CacheManagerPeerListener监听从成员们发向当前CacheManager的消息 配置CacheManagerPeerListener需要指定一个CacheManagerPeerListenerFactory 它以插件的机制实现 用来创建CacheManagerPeerListener         cacheManagerPeerListenerFactory的属性有         class – 一个完整的工厂类名         properties – 只对这个工厂有意义的属性 使用逗号分隔         Ehcache有一个内置的基于RMI的分布系统 它的监听器是RMICacheManagerPeerListener 这个监听器可以用        RMICacheManagerPeerListenerFactory来配置         cacheManagerPeerListenerFactoryclass= net sf ehcache distribution RMICacheManagerPeerListenerFactory properties= hostName=localhost port= /socketTimeoutMillis= 有效的属性是         hostname (可选) – 运行监听器的服务器名称 标明了做为集群群组的成员的地址 同时也是你想要控制的从集群中接收消息的接口

        在CacheManager初始化的时候会检查hostname是否可用         如果hostName不可用 CacheManager将拒绝启动并抛出一个连接被拒绝的异常         如果指定 hostname将使用InetAddress getLocalHost() getHostAddress()来得到         警告 不要将localhost配置为本地地址 因为它在网络中不可见将会导致不能从远程服务器接收信息从而不能复制 在同一台机器上有多个CacheManager的时候 你应该只用localhost来配置         port – 监听器监听的端口         socketTimeoutMillis (可选) – Socket超时的时间 默认是 ms 当你socket同步缓存请求地址比较远 不是本地局域网 你可能需要把这个时间配置大些 不然很可能延时导致同步缓存失败         配置CacheReplicators        每个要进行同步的cache都需要设置一个用来向CacheManagerr的成员复制消息的缓存事件监听器 这个工作要通过为每个cache的配置增加一个cacheEventListenerFactory元素来完成         ! Sample cache named sampleCache cache name= sampleCache maxElementsInMemory= eternal= false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk= false cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory properties= replicateAsynchronously=true replicatePuts=true replicateUpdates=true replicateUpdatesViaCopy=false replicateRemovals=true //cacheclass – 使用net sf ehcache distribution RMICacheReplicatorFactory        这个工厂支持以下属性         replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers 默认是true         replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制 默认是true         replicateRemovals= true | false – 当元素移除的时候是否进行复制 默认是true         replicateAsynchronously=true | false – 复制方式是异步的(指定为true时)还是同步的(指定为false时) 默认是true         replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制指定为true时为复制 默认是true         replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制(指定为true时为复制) 默认是true         你可以使用ehcache的默认行为从而减少配置的工作量 默认的行为是以异步的方式复制每件事 你可以像下面的例子一样减少RMICacheReplicatorFactory的属性配置         ! Sample cache named sampleCache All missing RMICacheReplicatorFactory properties default to true cache name= sampleCache maxElementsInMemory= eternal= true overflowToDisk= false memoryStoreEvictionPolicy= LFU cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory //cache        常见的问题        Windows上的Tomcat        有一个Tomcat或者是JDK的bug 在tomcat启动时如果tomcat的安装路径中有空格的话 在启动时RMI监听器会失败 参见 bin/wa?A =ind L=rmi usersP= 和 doc/faq howto bugs/l         由于在Windows上安装Tomcat默认是装在 Program Files 文件夹里的 所以这个问题经常发生         广播阻断        自动的peer discovery与广播息息相关 广播可能被路由阻拦 像Xen和VMWare这种虚拟化的技术也可以阻拦广播 如果这些都打开了 你可能还在要将你的网卡的相关配置打开 一个简单的办法可以告诉广播是否有效         那就是使用ehcache remote debugger来看 心跳 是否可用         广播传播的不够远或是传得太远        你可以通过设置badly misnamed time to live来控制广播传播的距离 用广播IP协议时 timeToLive的值指的是数据包可以传递的域或是范围 约定如下         是限制在同一个服务器        是限制在同一个子网        是限制在同一个网站        是限制在同一个region        是限制在同一个大洲        是不限制        译者按 上面这些资料翻译的不够准确 请读者自行寻找原文理解吧         在Java实现中默认值是 也就是在同一个子网中传播 改变timeToLive属性可以限制或是扩展传播的范围    

三 RMI方式缓存集群/配置分布式缓存         RMI 是 Java 的一种远程方法调用技术 是一种点对点的基于 Java 对象的通讯方式 EhCache 从 版本开始就支持 RMI 方式的缓存集群 在集群环境中 EhCache 所有缓存对象的键和值都必须是可序列化的 也就是必须实现 java io Serializable 接口 这点在其它集群方式下也是需要遵守的         下图是 RMI 集群模式的结构图

         采用 RMI 集群模式时 集群中的每个节点都是对等关系 并不存在主节点或者从节点的概念 因此节点间必须有一个机制能够互相认识对方 必须知道其它节点的信息 包括主机地址 端口号等 EhCache 提供两种节点的发现方式 手工配置和自动发现 手工配置方式要求在每个节点中配置其它所有节点的连接信息 一旦集群中的节点发生变化时 需要对缓存进行重新配置         由于 RMI 是 Java 中内置支持的技术 因此使用 RMI 集群模式时 无需引入其它的 Jar 包 EhCache 本身就带有支持 RMI 集群的功能 使用 RMI 集群模式需要在 ehcache xml 配置文件中定义 cacheManagerPeerProviderFactory 节点         分布式同步缓存要让这边的cache知道对方的cache 叫做Peer Discovery(成员发现) EHCache实现成员发现的方式有两种         手动查找        A 在ehcache xml中配置PeerDiscovery成员发现对象        Server 配置 配置本地hostName port是 分别监听 : 的mobileCache和 : 的mobileCache 注意这里的mobileCache是缓存的名称 分别对应着server server 的cache的配置         ?xml version= encoding= gbk ?ehcache xmlns:xsi= instance xsi:noNamespaceSchemaLocation= ehcache xsd         diskStore path= java io tmpdir /        !         集群多台服务器中的缓存 这里是要同步一些服务器的缓存        server hostName: port: cacheName:mobileCache        server hostName: port: cacheName:mobileCache        server hostName: port: cacheName:mobileCache        注意 每台要同步缓存的服务器的RMI通信socket端口都不一样 在配置的时候注意设置                ! server 的cacheManagerPeerProviderFactory配置         cacheManagerPeerProviderFactory        class= net sf ehcache distribution RMICacheManagerPeerProviderFactory         properties= hostName=localhost         port=         socketTimeoutMillis=         peerDiscovery=manual         rmiUrls=// : /mobileCache|// : /mobileCache         //ehcache以上注意cacheManagerPeerProviderFactory元素出现的位置在diskStore下   

    同样在你的另外 台服务器上增加配置        Server 配置本地host port为 分别同步 : 的mobileCache和 : 的mobileCache        ! server 的cacheManagerPeerProviderFactory配置 cacheManagerPeerProviderFactory        class= net sf ehcache distribution RMICacheManagerPeerProviderFactory         properties= hostName=localhost         port=         socketTimeoutMillis=         peerDiscovery=manual         rmiUrls=// : /mobileCache|// : /mobileCache /Server 配置本地host port为 分别同步 : 的mobileCache缓存和 : 的mobileCache缓存        ! server 的cacheManagerPeerProviderFactory配置 cacheManagerPeerProviderFactory        class= net sf ehcache distribution RMICacheManagerPeerProviderFactory         properties= hostName=localhost         port=         socketTimeoutMillis=         peerDiscovery=manual         rmiUrls=// : /mobileCache|// : /mobileCache /这样就在三台不同的服务器上配置了手动查找cache的PeerProvider成员发现的配置了 值得注意的是你在配置rmiUrls的时候要特别注意url不能重复出现 并且端口 地址都是对的         如果指定 hostname将使用InetAddress getLocalHost() getHostAddress()来得到         警告 不要将localhost配置为本地地址 因为它在网络中不可见将会导致不能从远程服务器接收信息从而不能复制 在同一台机器上有多个CacheManager的时候 你应该只用localhost来配置         B 下面配置缓存和缓存同步监听 需要在每台服务器中的ehcache xml文件中增加cache配置和cacheEventListenerFactory cacheLoaderFactory的配置        defaultCache maxElementsInMemory= eternal= false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk= false /!         配置自定义缓存        maxElementsInMemory:缓存中允许创建的最大对象数        eternal:缓存中对象是否为永久的 如果是 超时设置将被忽略 对象从不过期         timeToIdleSeconds:缓存数据空闲的最大时间 也就是说如果有一个缓存有多久没有被访问就会被销毁 如果该值是 就意味着元素可以停顿无穷长的时间         timeToLiveSeconds:缓存数据存活的时间 缓存对象最大的的存活时间 超过这个时间就会被销毁 这只能在元素不是永久驻留时有效 如果该值是 就意味着元素可以停顿无穷长的时间         overflowToDisk:内存不足时 是否启用磁盘缓存         memoryStoreEvictionPolicy:缓存满了之后的淘汰算法         每一个小时更新一次缓存( 小时过期) cache name= mobileCache         maxElementsInMemory=         eternal= false         overflowToDisk= true         timeToIdleSeconds=         timeToLiveSeconds=         memoryStoreEvictionPolicy= LFU         !         RMI缓存分布同步查找 class使用net sf ehcache distribution RMICacheReplicatorFactory        这个工厂支持以下属性         replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers 默认是true         replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制 默认是true         replicateRemovals= true | false – 当元素移除的时候是否进行复制 默认是true         replicateAsynchronously=true | false – 复制方式是异步的 指定为true时 还是同步的 指定为false时 默认是true         replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true         replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true         asynchronousReplicationIntervalMillis=                 ! 监听RMI同步缓存对象配置 注册相应的的缓存监听类 用于处理缓存事件 如put remove update 和expire         cacheEventListenerFactory        class= net sf ehcache distribution RMICacheReplicatorFactory         properties= replicateAsynchronously=true /        replicatePuts=true         replicateUpdates=true         replicateUpdatesViaCopy=false         replicateRemovals=true         ! 用于在初始化缓存 以及自动设置         bootstrapCacheLoaderFactory class= net sf ehcache bootstrap BootstrapCacheLoaderFactory //cache        C 这样就完成了 台服务器的配置 下面给出server 的完整的ehcache xml的配置        ?xml version= encoding= gbk ?ehcache xmlns:xsi= instance xsi:noNamespaceSchemaLocation= ehcache xsd         diskStore path= java io tmpdir /        !    

    集群多台服务器中的缓存 这里是要同步一些服务器的缓存        server hostName: port: cacheName:mobileCache        server hostName: port: cacheName:mobileCache        server hostName: port: cacheName:mobileCache        注意每台要同步缓存的服务器的RMI通信socket端口都不一样 在配置的时候注意设置                ! server 的cacheManagerPeerProviderFactory配置         cacheManagerPeerProviderFactory        class= net sf ehcache distribution RMICacheManagerPeerProviderFactory         properties= hostName=localhost         port=         socketTimeoutMillis=         peerDiscovery=manual         rmiUrls=// : /mobileCache|// : /mobileCache         /        defaultCache maxElementsInMemory= eternal= false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk= false /        !         配置自定义缓存        maxElementsInMemory:缓存中允许创建的最大对象数        eternal:缓存中对象是否为永久的 如果是 超时设置将被忽略 对象从不过期         timeToIdleSeconds:缓存数据空闲的最大时间 也就是说如果有一个缓存有多久没有被访问就会被销毁         如果该值是 就意味着元素可以停顿无穷长的时间         timeToLiveSeconds:缓存数据存活的时间 缓存对象最大的的存活时间 超过这个时间就会被销毁         这只能在元素不是永久驻留时有效 如果该值是 就意味着元素可以停顿无穷长的时间         overflowToDisk:内存不足时 是否启用磁盘缓存         memoryStoreEvictionPolicy:缓存满了之后的淘汰算法         每一个小时更新一次缓存( 小时过期)                cache name= mobileCache         maxElementsInMemory=         eternal= false         overflowToDisk= true         timeToIdleSeconds=         timeToLiveSeconds=         memoryStoreEvictionPolicy= LFU         !         RMI缓存分布同步查找 class使用net sf ehcache distribution RMICacheReplicatorFactory        这个工厂支持以下属性         replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers 默认是true         replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制 默认是true         replicateRemovals= true | false – 当元素移除的时候是否进行复制 默认是true         replicateAsynchronously=true | false – 复制方式是异步的 指定为true时 还是同步的 指定为false时 默认是true         replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true         replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true         asynchronousReplicationIntervalMillis=                 ! 监听RMI同步缓存对象配置 注册相应的的缓存监听类 用于处理缓存事件 如put remove update 和expire         cacheEventListenerFactory        class= net sf ehcache distribution RMICacheReplicatorFactory         properties= replicateAsynchronously=true /        replicatePuts=true         replicateUpdates=true         replicateUpdatesViaCopy=false         replicateRemovals=true         ! 用于在初始化缓存 以及自动设置         bootstrapCacheLoaderFactory class= net sf ehcache bootstrap BootstrapCacheLoaderFactory /        /cache/ehcache 自动发现        自动发现配置和手动查找的方式有一点不同 其他的地方都基本是一样的 同样在ehcache xml中增加配置 配置如下        ! 搜索某个网段上的缓存timeToLive        是限制在同一个服务器        是限制在同一个子网        是限制在同一个网站        是限制在同一个region        是限制在同一个大洲        是不限制 cacheManagerPeerProviderFactory        class= net sf ehcache distribution RMICacheManagerPeerProviderFactory         properties= peerDiscovery=automatic multicastGroupAddress=         multicastGroupPort= timeToLive= / lishixinzhi/Article/program/Java/hx/201311/25706

采用近期最少使用(LFU)算法仿真请求分页系统(C语言实现)

你这个问题拿到百度上是不可能有人回答你的,而且像这种操作系统的问题,步骤这么多是要收费的。去csdn求助试试。

如何用java实现fifo页面置换算法

[fifo.rar] - 操作系统中内存页面的先进先出的替换算法fifo

[先进先出页面算法程序.rar] - 分别实现最佳置换算法(optimal)、先进先出(fifo)页面置换算法和最近最久未使用(LRU)置换算法,并给出各算法缺页次数和缺页率。

[0022.rar] - 模拟分页式虚拟存储管理中硬件的地址转换和缺页中断,以及选择页面调度算法处理缺页中断

[Change.rar] - 用java实现操作系统的页面置换 其中包括 最佳置换算法(Optimal)、先进先出算法(First-in, First-out) 、最近最久不用的页面置换算法(LeastRecently Used Replacement)三种算法的实现

[M_Management.rar] - 操作系统中内存管理页面置换算法的模拟程序,采用的是LRU置换算法

[detail_of_44b0x_TCPIP.rar] - TCPIP 程序包加载到44b0x 的ADS1.2工程文件的说明书。说名了加载过程的细节和如何处理演示程序和代码。演示代码已经上传,大家可以搜索

[OperatingSystemPageReplacementAlgorithm.rar] - java操作系统页面置换算法: (1)进先出的算法(fifo) (2)最近最少使用的算法(LRU) (3)最佳淘汰算法(OPT) (4)最少访问页面算法(LFU) (注:由本人改成改进型Clock算法) (5)最近最不经常使用算法(NUR)

Redis的缓存淘汰策略LRU与LFU

Redis缓存淘汰策略与Redis键的过期删除策略并不完全相同,前者是在Redis内存使用超过一定值的时候(一般这个值可以配置)使用的淘汰策略;而后者是通过定期删除+惰性删除两者结合的方式淘汰内存过期键的。

这里参照官方文档的解释重新叙述一遍过期删除策略:当某个key被设置了过期时间之后,客户端每次对该key的访问(读写)都会事先检测该key是否过期,如果过期就直接删除;但有一些键只访问一次,因此需要主动删除,默认情况下redis每秒检测10次,检测的对象是所有设置了过期时间的键集合,每次从这个集合中随机检测20个键查看他们是否过期,如果过期就直接删除,如果删除后还有超过25%的集合中的键已经过期,那么继续检测过期集合中的20个随机键进行删除。这样可以保证过期键最大只占所有设置了过期时间键的25%。

在Java中LRU的实现方式是使用HashMap结合双向链表,HashMap的值是双向链表的节点,双向链表的节点也保存一份key value。

LFU是在Redis4.0后出现的,LRU的最近最少使用实际上并不精确,考虑下面的情况,如果在|处删除,那么A距离的时间最久,但实际上A的使用频率要比B频繁,所以合理的淘汰策略应该是淘汰B。LFU就是为应对这种情况而生的。

java为什么使用缓存实现抢答

您是否在询问为什么使用缓存,缓存是用来存储数据的。

FIFO先入先出,很好理解,就和队列一样,先进队列的先出队列,LRU 最近最少使用,意思就是最近读取的数据放在最前面,最早读取的数据放在最后面,如果这个时候有新的数据进来,那么最后面存储的数据淘汰,LFU最不常使用,意思就是对存储的数据都会有一个计数引用,然后队列按数据引用次数排序,引用数多的排在最前面,引用数少的排在后面。如果这个时候有新的数据进来,把最后面的数据删除,把新进数据排在最后面,且引用次数为1。

ehcache java 对象缓存怎么实现

1.技术背景:

    系统缓存是位于应用程序与物理数据源之间,用于临时存放复制数据的内存区域,目的是为减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能。缓存设想内存是有限的,缓存的时效性也是有限的,所以可以设定内存数量的大小可以执行失效算法,可以在内存满了的情况下,按照最少访问等算法将缓存直接移除或切换到硬盘上。

    Ehcache从Hibernate发展而来,逐渐涵盖了Cache界的全部功能,是目前发展势头最好的一个项目,具有快速、简单、低消耗、扩展性强、支持对象或序列化缓存,支持缓存或元素的失效,提供LRU、LFU和FIFO缓存策略,支持内存缓存和硬盘缓存和分布式缓存机制等特点。其中Cache的存储方式为内存或磁盘(ps:无须担心容量问题)

2.EhCahe的类层次介绍:

    主要分为三层,最上层是CacheManager,它是操作Ehcache的入口。可以通过CacheManager.getInstance()获得一个单子的CacheManager,或者通过CacheManager的构造函数创建一个新的CacheManager。每个CacheManger都管理多个Cache。每个Cache都以一种类Hash的方式,关联多个Element。Element就是我们用于存放缓存内容的地方。

3.环境搭建:

    很简单只需要将ehcache-2.1.0-distribution.tar.gz和ehcache-web-2.0.2-distribution.tar.gz挤压的jar包放入WEB-INF/lib下。

    再创建一个重要的配置文件ehcache.xml,可以从ehcache组件包中拷贝一个,也可以自己建立一个,需要放到classpath下,一般放于/WEB-INF/classed/ehcache.xml;具体的配置文件可以网上搜一下

4.实际运用

    一个网站的首页估计是被访问次数最多的,我们可以考虑给首页做一个页面缓存;

    缓存策略:应该是某个固定时间之内不变的,比如说2分钟更新一次,以应用结构page-filter-action-service-dao-db为例。

    位置:页面缓存做到尽量靠近客户的地方,就是在page和filter之间,这样的优点就是第一个用户请求后,页面被缓存,第二个用户在请求,走到filter这个请求就结束了,需要在走到action-service-dao-db,好处当然是服务器压力大大降低和客户端页面响应速度加快。

    首页页面缓存存活时间定为2分钟,也就是参数timeToLiveSeconds(缓存的存活时间)应该设置为120,同时timeToIdleSeconds(多长时间不访问缓存,就清楚该缓存)最好也设为2分钟或者小于2分钟。

接着我们来看一下SimplePageCachingFilter 的配置,

   

filter

filter-nameindexCacheFilterfilter-name

filter-class

net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter

filter-class

filter

filter-mapping

filter-nameindexCacheFilterfilter-name

url-pattern*index.actionurl-pattern

filter-mapping

   

将上述代码加入到web.xml,那么当打开首页时,你会发现2分钟才会有一堆sql语句出现在控制台,也可以调整为5分钟,总之一切尽在掌控之中。

 

当然,如果你像缓存首页的部分内容时,你需要使用SimplePageFragmentCachingFilter这个filter,我看一下:

filter

filter-nameindexCacheFilterfilter-name

filter-class

net.sf.ehcache.constructs.web.filter.SimplePageFragmentCachingFilter

filter-class

filter

filter-mapping

filter-nameindexCacheFilterfilter-name

url-pattern*/index_right.jspurl-pattern

filter-mapping

   

如此我们将jsp页面通过jsp:include到其他页面,这样就做到了页面局部缓存的效果,这一点貌似没有oscache的tag好用。

 

此外cachefilter中还有一个特性,就是gzip,也就是缓存中的元素是被压缩过的,如果客户端浏览器支持压缩的话,filter会直接返回压缩过的流,这样节省了带宽,把解压的工作交给了客户端浏览即可,当然如果客户端不支持gzip,那么filter会把缓存的元素拿出来解压后在返回给客户端浏览器(大多数爬虫是不支持gzip的,所以filter也会解压后在返回流)。

总之,Ehcache是一个非常轻量级的缓存实现,而且从1.2之后支持了集群,而且是hibernate默认的缓存provider,本文主要介绍Ehcahe对页面缓存的支持,但是它的功能远不止如此,要用好缓存,对J2ee中缓存的原理、适用范围、适用场景等等都需要比较深刻的理解,这样才能用好用对缓存。

 

为了大家通过实际例子加深了解与场景运用,在奉献一个实例:

*在Spring中运用EhCache

    适用任意一个现有开源Cache Framework,要求可以Cache系统中service或者DAO层的get/find等方法返回结果,如果数据更新(适用了Create/update/delete),则刷新cache中相应的内容。

    根据需求,计划适用Spring AOP+enCache来实现这个功能,采用ehCache原因之一就是Spring提供了enCache的支持,至于为何仅仅支持ehcache而不支持oscache和jbosscache就无从得知了。

    AOP少不了拦截器,先创建一个实现了MethodInterceptor接口的拦截器,用来拦截Service/DAO的方法调用,拦截到方法后,搜索该方法的结果在cache中是否存在,如果存在,返回cache中结果,如果不存在返回数据库查询结果,并将结果返回到缓存。

public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean

{

private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);

private Cache cache;

public void setCache(Cache cache) {

this.cache = cache;

}

public MethodCacheInterceptor() {

super();

}

/**

* 拦截Service/DAO 的方法,并查找该结果是否存在,如果存在就返回cache 中的值,

* 否则,返回数据库查询结果,并将查询结果放入cache

*/

public Object invoke(MethodInvocation invocation) throws Throwable {

String targetName = invocation.getThis().getClass().getName();

String methodName = invocation.getMethod().getName();

Object[] arguments = invocation.getArguments();

Object result;

logger.debug("Find object from cache is " + cache.getName());

String cacheKey = getCacheKey(targetName, methodName, arguments);

Element element = cache.get(cacheKey);

Page 13 of 26

if (element == null) {

logger.debug("Hold up method , Get method result and create cache........!");

result = invocation.proceed();

element = new Element(cacheKey, (Serializable) result);

cache.put(element);

}

return element.getValue();

}

/**

* 获得cache key 的方法,cache key 是Cache 中一个Element 的唯一标识

* cache key 包括包名+类名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser

*/

private String getCacheKey(String targetName, String methodName, Object[] arguments) {

StringBuffer sb = new StringBuffer();

sb.append(targetName).append(".").append(methodName);

if ((arguments != null)  (arguments.length != 0)) {

for (int i = 0; i  arguments.length; i++) {

sb.append(".").append(arguments[i]);

}

}

return sb.toString();

}

/**

* implement InitializingBean,检查cache 是否为空

*/

public void afterPropertiesSet() throws Exception {

Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");

}

}

   

上面的代码可以看到,在方法invoke中,完成了搜索cache/新建cache的功能

随后,再建立一个拦截器MethodCacheAfterAdvice,作用是在用户进行create/update/delete操作时来刷新、remove相关cache内容,这个拦截器需要实现AfterRetruningAdvice接口,将会在所拦截的方法执行后执行在afterReturning(object arg0,Method arg1,Object[] arg2,object arg3)方法中所预定的操作

  

public class MethodCacheAfterAdvice implements AfterReturningAdvice, InitializingBean

{

private static final Log logger = LogFactory.getLog(MethodCacheAfterAdvice.class);

private Cache cache;

Page 15 of 26

public void setCache(Cache cache) {

this.cache = cache;

}

public MethodCacheAfterAdvice() {

super();

}

public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws

Throwable {

String className = arg3.getClass().getName();

List list = cache.getKeys();

for(int i = 0;ilist.size();i++){

String cacheKey = String.valueOf(list.get(i));

if(cacheKey.startsWith(className)){

cache.remove(cacheKey);

logger.debug("remove cache " + cacheKey);

}

}

}

public void afterPropertiesSet() throws Exception {

Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");

}

}

   

该方法获取目标class的全名,如:com.co.cache.test.TestServiceImpl,然后循环cache的key list,刷新/remove cache中所有和该class相关的element。

 

接着就是配置encache的属性,如最大缓存数量、cache刷新的时间等等。

ehcache

diskStore path="c:\\myapp\\cache"/

defaultCache

maxElementsInMemory="1000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

overflowToDisk="true"

/

cache name="DEFAULT_CACHE"

maxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="300000"

timeToLiveSeconds="600000"

overflowToDisk="true"

/

/ehcache

   

这里需要注意的是defaultCache定义了一个默认的cache,这个Cache不能删除,否则会抛出No default cache is configured异常。另外由于使用拦截器来刷新Cache内容,因此在定义cache生命周期时可以定义较大的数值,timeToIdleSeconds="30000000",timeToLiveSeconds="6000000",好像还不够大?

 

然后再将Cache和两个拦截器配置到Spring的配置文件cache.xml中即可,需要创建两个“切入点”,分别用于拦截不同方法名的方法。在配置application.xml并且导入cache.xml。这样一个简单的Spring+Encache框架就搭建完成。

java实现lfu的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于Java实现接口、java实现lfu的信息别忘了在本站进行查找喔。