您的位置:首页 > 其它

Ehcache实例

2016-05-22 15:12 316 查看
创建一个maven项目

一、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>

二、在resources添加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>

三、java代码

 
   package cnblogs.ehcache;

     import net.sf.ehcache.Cache;

     import net.sf.ehcache.CacheManager;

     import net.sf.ehcache.Element;

public class CacheDemo {

    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
b38b
("-------------------------");
        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中的数据变化后,过一段时间就会更新到缓存中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: