一、pom.xml 依赖项

 <dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.8.3</version>
</dependency> <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>

二、ehcache.xml

 <?xml version="1.0" encoding="UTF-8"?>

 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
monitoring="autodetect" dynamicConfig="true"> <diskStore path="java.io.tmpdir" /> <defaultCache maxEntriesLocalHeap="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30"
maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap" />
</defaultCache> <cache name="sampleCache1" maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000" eternal="false" diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300" timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU" transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache> <cache name="sampleCache2" maxEntriesLocalHeap="1000" eternal="true"
memoryStoreEvictionPolicy="FIFO" /> </ehcache>

三、示例代码

 package cnblogs.ehcache;

 import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element; public class App {
public static void main(String[] args) throws InterruptedException {
CacheManager manager = CacheManager.create(); // 取出所有的cacheName
String names[] = manager.getCacheNames();
System.out.println("----all cache names----");
for (int i = 0; i < names.length; i++) {
System.out.println(names[i]);
} System.out.println("----------------------");
// 得到一个cache对象
Cache cache1 = manager.getCache(names[0]); // 向cache1对象里添加缓存
cache1.put(new Element("key1", "values1"));
Element element = cache1.get("key1"); // 读取缓存
System.out.println("key1 \t= " + element.getObjectValue()); // 手动创建一个cache(ehcache里必须有defaultCache存在,"test"可以换成任何值)
Cache cache2 = new Cache("test", 1, true, false, 2, 3);
manager.addCache(cache2); cache2.put(new Element("jimmy", "菩提树下的杨过")); // 故意停1.5秒,以验证是否过期
Thread.sleep(1500); Element eleJimmy = cache2.get("jimmy"); //1.5s < 2s 不会过期
if (eleJimmy != null) {
System.out.println("jimmy \t= " + eleJimmy.getObjectValue());
} //再等上0.5s, 总时长:1.5 + 0.5 >= min(2,3),过期
Thread.sleep(500); eleJimmy = cache2.get("jimmy"); if (eleJimmy != null) {
System.out.println("jimmy \t= " + eleJimmy.getObjectValue());
} // 取出一个不存在的缓存项
System.out.println("fake \t= " + cache2.get("fake")); manager.shutdown();
} }

运行结果:

----all cache names----
sampleCache2
sampleCache1
----------------------
key1     = values1
jimmy     = 菩提树下的杨过
fake     = null

四、关于timeToLiveSeconds、timeToIdleSeconds

这二个参数直接影响缓存项的过期时间,看文档说明基本上没啥用,直接看net.sf.ehcache.Element源码的片段:

 /**
* The amount of time for the element to live, in seconds. 0 indicates unlimited.
*/
private volatile int timeToLive = Integer.MIN_VALUE; /**
* The amount of time for the element to idle, in seconds. 0 indicates unlimited.
*/
private volatile int timeToIdle = Integer.MIN_VALUE; /**
* Sets time to Live
* <P/>
* Value must be a positive integer, 0 means infinite time to live.
* <P/>
* If calling this method with 0 as the parameter, consider using {@link #setEternal(boolean)}
* or make sure you also explicitly call {@link #setTimeToIdle(int)}.
*
* @param timeToLiveSeconds the number of seconds to live
*/
public void setTimeToLive(final int timeToLiveSeconds) {
if (timeToLiveSeconds < 0) {
throw new IllegalArgumentException("timeToLive can't be negative");
}
this.cacheDefaultLifespan = false;
this.timeToLive = timeToLiveSeconds;
} /**
* Sets time to idle
* <P/>
* Value must be a positive integer, 0 means infinite time to idle.
* <P/>
* If calling this method with 0 as the parameter, consider using {@link #setEternal(boolean)}
* or make sure you also explicitly call {@link #setTimeToLive(int)}.
*
* @param timeToIdleSeconds the number of seconds to idle
*/
public void setTimeToIdle(final int timeToIdleSeconds) {
if (timeToIdleSeconds < 0) {
throw new IllegalArgumentException("timeToIdle can't be negative");
}
this.cacheDefaultLifespan = false;
this.timeToIdle = timeToIdleSeconds;
} /**
* An element is expired if the expiration time as given by {@link #getExpirationTime()} is in the past.
*
* @return true if the Element is expired, otherwise false. If no lifespan has been set for the Element it is
* considered not able to expire.
* @see #getExpirationTime()
*/
public boolean isExpired() {
if (!isLifespanSet() || isEternal()) {
return false;
} long now = System.currentTimeMillis();
long expirationTime = getExpirationTime(); return now > expirationTime;
} /**
* An element is expired if the expiration time as given by {@link #getExpirationTime()} is in the past.
* <p>
* This method in addition propogates the default TTI/TTL values of the supplied cache into this element.
*
* @param config config to take default parameters from
* @return true if the Element is expired, otherwise false. If no lifespan has been set for the Element it is
* considered not able to expire.
* @see #getExpirationTime()
*/
public boolean isExpired(CacheConfiguration config) {
if (cacheDefaultLifespan) {
if (config.isEternal()) {
timeToIdle = 0;
timeToLive = 0;
} else {
timeToIdle = TimeUtil.convertTimeToInt(config.getTimeToIdleSeconds());
timeToLive = TimeUtil.convertTimeToInt(config.getTimeToLiveSeconds());
}
}
return isExpired();
} /**
* Returns the expiration time based on time to live. If this element also has a time to idle setting, the expiry
* time will vary depending on whether the element is accessed.
*
* @return the time to expiration
*/
public long getExpirationTime() {
if (!isLifespanSet() || isEternal()) {
return Long.MAX_VALUE;
} long expirationTime = 0;
long ttlExpiry = creationTime + TimeUtil.toMillis(getTimeToLive()); long mostRecentTime = Math.max(creationTime, lastAccessTime);
long ttiExpiry = mostRecentTime + TimeUtil.toMillis(getTimeToIdle()); if (getTimeToLive() != 0 && (getTimeToIdle() == 0 || lastAccessTime == 0)) {
expirationTime = ttlExpiry;
} else if (getTimeToLive() == 0) {
expirationTime = ttiExpiry;
} else {
expirationTime = Math.min(ttlExpiry, ttiExpiry);
}
return expirationTime;
} /**
* @return true if the element is eternal
*/
public boolean isEternal() {
return (0 == timeToIdle) && (0 == timeToLive);
} /**
* Sets whether the element is eternal.
*
* @param eternal
*/
public void setEternal(final boolean eternal) {
if (eternal) {
this.cacheDefaultLifespan = false;
this.timeToIdle = 0;
this.timeToLive = 0;
} else if (isEternal()) {
this.cacheDefaultLifespan = false;
this.timeToIdle = Integer.MIN_VALUE;
this.timeToLive = Integer.MIN_VALUE;
}
} /**
* Whether any combination of eternal, TTL or TTI has been set.
*
* @return true if set.
*/
public boolean isLifespanSet() {
return this.timeToIdle != Integer.MIN_VALUE || this.timeToLive != Integer.MIN_VALUE;
} /**
* @return the time to live, in seconds
*/
public int getTimeToLive() {
if (Integer.MIN_VALUE == timeToLive) {
return 0;
} else {
return timeToLive;
}
} /**
* @return the time to idle, in seconds
*/
public int getTimeToIdle() {
if (Integer.MIN_VALUE == timeToIdle) {
return 0;
} else {
return timeToIdle;
}
} /**
* Set the default parameters of this element - those from its enclosing cache.
* @param tti TTI in seconds
* @param ttl TTL in seconds
* @param eternal <code>true</code> if the element is eternal.
*/
protected void setLifespanDefaults(int tti, int ttl, boolean eternal) {
if (eternal) {
this.timeToIdle = 0;
this.timeToLive = 0;
} else if (isEternal()) {
this.timeToIdle = Integer.MIN_VALUE;
this.timeToLive = Integer.MIN_VALUE;
} else {
timeToIdle = tti;
timeToLive = ttl;
}
}

结论:

a) timeToIdleSeconds(空闲时间)、timeToLiveSeconds(生存时间)都设置为0时,表示不过期

b) 如果只有timeToLiveSeconds设置>0的值,则Element的过期时间为 timeToLiveSeconds

c) 如果只有timeToIdleSeconds设置>0的值,则Element的过期时间为 (上次访问时间+timeToIdleSeconds),说得更通俗点,上次get过了,现在又想get,若二次get的时间间隔>timeToIdleSeconds,则过期(即:最后一次get出来为null)

d) 如果timeToLiveSeconds、timeToIdleSeconds都有>0的值,则最终过期时间为 b),c)规则综合起来,取二者的最小值

测试1:

     @Test
public void testTimeToIdleSeconds() throws InterruptedException {
CacheManager manager = CacheManager.create(); Cache myCache = new Cache("MyCache", 1, true, false, 0, 0); // Cache上设置为永不过期
manager.addCache(myCache); String key = "A"; System.out.println("-------------------------");
Element elementPut = new Element(key, "Some Value", 2, 0); // timeToIdleSeconds为2秒 myCache.put(elementPut);// 放入缓存
System.out.println(myCache.get(key));// 取出显示 Thread.sleep(1500);// 停1.5秒
System.out.println(myCache.get(key));// 再次取出 Thread.sleep(1500);// 停1.5秒
System.out.println(myCache.get(key));// 虽然总时间已达3秒,但刚刚被访问过了,所以又可以再"活"2秒,仍然有效 Thread.sleep(2500);// 停2.5秒
System.out.println(myCache.get(key));// 距离上次访问已过2.5s,已经>2s,过期 }

输出结果

[ key = A, value=Some Value, version=1, hitCount=1, CreationTime = 1407898361782, LastAccessTime = 1407898361787 ]
[ key = A, value=Some Value, version=1, hitCount=2, CreationTime = 1407898361782, LastAccessTime = 1407898363287 ]
[ key = A, value=Some Value, version=1, hitCount=3, CreationTime = 1407898361782, LastAccessTime = 1407898364787 ]
null

测试2:

     @Test
public void testTimeToLiveSeconds() throws InterruptedException {
CacheManager manager = CacheManager.create(); Cache myCache = new Cache("MyCache", 1, true, false, 0, 0); // Cache上设置为永不过期
manager.addCache(myCache); String key = "A"; System.out.println("-------------------------");
Element elementPut = new Element(key, "Some Value", 0, 2); // timeToLiveSeconds为2秒 myCache.put(elementPut);// 放入缓存
System.out.println(myCache.get(key));// 取出显示 Thread.sleep(1500);// 停1.5秒
System.out.println(myCache.get(key));// 再次取出(1.5s<2s,还"活"着) Thread.sleep(1500);// 停1.5秒
System.out.println(myCache.get(key));// 总时间已达3s,>2s,已过期) }

输出结果

[ key = A, value=Some Value, version=1, hitCount=1, CreationTime = 1407898423291, LastAccessTime = 1407898423296 ]
[ key = A, value=Some Value, version=1, hitCount=2, CreationTime = 1407898423291, LastAccessTime = 1407898424797 ]
null

测试3:

 @Test
public void testTimeToIdleSecondsAndTimeToLiveSeconds()
throws InterruptedException {
CacheManager manager = CacheManager.create(); Cache myCache = new Cache("MyCache", 1, true, false, 0, 0); // Cache上设置为永不过期
manager.addCache(myCache); String key = "A"; System.out.println("-------------------------");
Element elementPut = new Element(key, "Some Value", 2, 5); // timeToIdleSeconds为2秒,timeToLiveSeconds为3秒 myCache.put(elementPut);// 放入缓存
System.out.println(myCache.get(key));// 取出显示 Thread.sleep(1600);// 停1.6秒
System.out.println(myCache.get(key));// 再次取出(1.6s < min(2 ,5),还"活"着) Thread.sleep(1600);// 停1.6秒
System.out.println(myCache.get(key));// 总时间已达3.2s,< min((1.6+2) ,5),还"活"着) Thread.sleep(1600);// 停1.6秒
System.out.println(myCache.get(key));// 总时间已达4.8s,< min((3.2+2) ,5),还"活"着) Thread.sleep(500);// 停0.5秒
System.out.println(myCache.get(key));// 总时间已达4.8+0.5=5.3s,> min((4.8+2) ,5),过期) }

输出结果

[ key = A, value=Some Value, version=1, hitCount=1, CreationTime = 1407898480892, LastAccessTime = 1407898480897 ]
[ key = A, value=Some Value, version=1, hitCount=2, CreationTime = 1407898480892, LastAccessTime = 1407898482499 ]
[ key = A, value=Some Value, version=1, hitCount=3, CreationTime = 1407898480892, LastAccessTime = 1407898484099 ]
[ key = A, value=Some Value, version=1, hitCount=4, CreationTime = 1407898480892, LastAccessTime = 1407898485699 ]
null

关于这二个参数的设置,个人建议是:

a) 如果缓存的数据本身不存在更新(比如:一些几乎从来不动的基础数据),只设置timeToIdleSeconds,这样的好处是,如果缓存项一直有人在访问,就永远不会过期,反之,如果没人用,空闲一段时间后,会自动过期,释放资源

b) 如果缓存的数据本身存在定期的更新问题(比如:天气预报之类每隔几小时,db中会更新的数据),可同时设置二个参数,timeToLiveSeconds的值应该要小于db中的更新周期,这样db中的数据变化后,过一段时间就会更新到缓存中

ehcache2.8.3入门示例:hello world的更多相关文章

  1. [WCF编程]1.WCF入门示例

    一.WCF是什么? Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,整合了原有的windows通讯的 .net Remotin ...

  2. Maven入门示例(3):自动部署至外部Tomcat

    Maven入门示例(3):自动部署至外部Tomcat 博客分类:  maven 2012原创   Maven入门示例(3):自动部署至外部Tomcat 上一篇,介绍了如何创建Maven项目以及如何在内 ...

  3. 1.【转】spring MVC入门示例(hello world demo)

    1. Spring MVC介绍 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于 ...

  4. 【java开发系列】—— spring简单入门示例

    1 JDK安装 2 Struts2简单入门示例 前言 作为入门级的记录帖,没有过多的技术含量,简单的搭建配置框架而已.这次讲到spring,这个应该是SSH中的重量级框架,它主要包含两个内容:控制反转 ...

  5. Spring MVC 入门示例讲解

    在本例中,我们将使用Spring MVC框架构建一个入门级web应用程序.Spring MVC 是Spring框架最重要的的模块之一.它以强大的Spring IoC容器为基础,并充分利用容器的特性来简 ...

  6. Couchbase之个人描述及入门示例

    本文不打算抄袭官方或者引用他人对Couchbase的各种描述,仅仅是自己对它的一点理解(错误之处,敬请指出),并附上一个入门示例. ASP.NET Web项目(其他web开发平台也一样)应用规模小的时 ...

  7. Velocity魔法堂系列一:入门示例

    一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...

  8. OUYA游戏开发核心技术剖析OUYA游戏入门示例——StarterKit

    第1章  OUYA游戏入门示例——StarterKit StarterKit是一个多场景的游戏示例,也是OUYA官方推荐给入门开发者分析的第一个完整游戏示例.本章会对StarterKit做详细介绍,包 ...

  9. Springmvc整合tiles框架简单入门示例(maven)

    Springmvc整合tiles框架简单入门示例(maven) 本教程基于Springmvc,spring mvc和maven怎么弄就不具体说了,这边就只简单说tiles框架的整合. 先贴上源码(免积 ...

随机推荐

  1. redmine + apache + mod_fcgid

    redmine默认是用webrick启动的,这种方法不适合生产环境,最好部署在apache下,本文介绍如何通过mod_fcgid启动. 首先要有一个能够启动的redmine,可以通过我之前的博文查看: ...

  2. (视频) 《快速创建网站》 3.1 WordPress 数据导入

    本文是<快速创建网站>系列的第5篇,如果你还没有看过之前的内容,建议你点击以下目录中的章节先阅读其他内容再回到本文. 访问本系列目录,请点击:http://devopshub.cn/tag ...

  3. SSH框架搭建详解 及 乱码处理

    http://www.360doc.com/content/15/1031/21/21693298_509739569.shtml struts 除了struts的mvc外,还有拦截器,国际化,str ...

  4. Asp.net MVC的Model Binder工作流程以及扩展方法(3) - DefaultModelBinder

    Default Binder是MVC中的清道夫,把守着Model Binder中的最后一道防线.如果我们没有使用Custom Model Binder等特殊处理,那么Model的绑定都是有Defaul ...

  5. Sql Server之旅——终点站 nolock引发的三级事件的一些思考

    曾今有件事情让我记忆犹新,那年刚来携程不久,马上就被安排写一个接口,供企鹅公司调用他们员工的差旅信息,然后我就三下五除二的给写好 了,上线之后,大概过了一个月...DBA那边报告数据库出现大量锁超时, ...

  6. JSP与Servelt的区别

    相同点: 两者都是服务端的技术,而JSP本质上就是Servelt: 都可以处理来自客户端的请求,都可以对请求作出响应: 都可以生成HTML页面返回. 不同点: 在实际开发中,对JSP编程成响应的HTM ...

  7. Java代码获取NTP服务器时间

    apache的commons-net包下面有ntp相关的实现类,主要类有: 1  org.apache.commons.net.ntp.NTPUDPClient ? 1  org.apache.com ...

  8. SQL Server中字符串转化为GUID的标量函数实现

        还是工作中遇到的需求,有时候和外部的系统对接,进行数据的核对功能,外部的系统有时候主键字段列数据类是UNIQUEIDENTIFER(GUID)类型的字符串格式,去除了GUID格式中的分隔符“- ...

  9. Sql server2012连接Sql server 2008时出现的问题:已成功与服务器建立连接,但在登陆过程中发生错误。(provider:SSL Provider,error:0-接收到的消息异常,或格式不正确。)

    以前连接是正常的,就这两天连不上了.(没有耐心的直接看末尾解决办法) 错误消息如下: 1.尝试读取或写入受保护的内存.这通常指示其他内存已损坏.(System.Data) 2.已成功与服务器建立连接, ...

  10. Windows Azure IP地址详解

    Windows Azure上的IP地址有以下几种: 公网IP地址 VIP ILPIP Reserved IP 内网IP地址 DIP Static IP VIP是动态分配的公网IP,VIP可以被分配到云 ...