【Ehcache】ehcache2.5.2缓存的使用

  缓存的名字是ehcache。。。老是记得是encache....  

 

  官方PDF文档:http://www.ehcache.org/documentation/ehcache-2.5.x-documentation.pdf

 

0.需要的jar包:

 

1.首先要了解缓存清除策略,官方文档给出的有

  超过缓存指定的数量的时候按指定策略清除缓存的数据。参考:MemoryStoreEvictionPolicy类:

LRU - least recently used(最近最少使用)
LFU - least frequently used(最不经常使用)
FIFO - first in first out, the oldest element by creation time(清除最早缓存的数据,不关心是否经常使用)
CLOCK---FIFO - first in first out, the oldest element by creation time.(与FIFO一样)

 

 

2.一个简单的使用

1.使用缓存

配置文件:

 <ehcache updateCheck="false" dynamicConfig="false">  
    <diskStore path="java.io.tmpdir"/>  
    
    <defaultCache  
        maxElementsInMemory="1000"  
        eternal="false"  
        overflowToDisk="true"  
        timeToIdleSeconds="120"  
        timeToLiveSeconds="120"  
        diskPersistent="false"  
        diskExpiryThreadIntervalSeconds="120"  
        memoryStoreEvictionPolicy="LRU"
    />      
     
    <cache name="cache_test" 
        maxElementsInMemory="2"  
        eternal="false"  
        timeToIdleSeconds="60"  
        timeToLiveSeconds="60"  
        maxElementsOnDisk="2"
        overflowToDisk="true"
        diskPersistent="false" 
        memoryStoreEvictionPolicy="FIFO"  
   />   
</ehcache> 

 

 

各配置参数的含义:
  maxElementsInMemory:缓存中允许创建的最大对象数

  maxElementsOnDisk:磁盘中允许的最多对象数
  eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
  timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0 就意味着元素可以停顿无穷长的时间。
  timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
  overflowToDisk:内存不足时,是否启用磁盘缓存。

  diskPersistent 是否持久化磁盘缓存,当这个属性的值为true时,系统在初始化时会在磁盘中查找文件名为cache名称,后缀名为data的文件。指重启jvm后,数据是否有效。默认为false。

  memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。


  如果应用需要配置多个不同命名并采用不同参数的Cache,可以相应修改配置文件,增加需要的Cache配置即可。

 

两个时间的详细解释:

  timeToLiveSeconds -->当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除;即缓存自创建日期起能够存活的最长时间,单位为秒(s)

  timeToIdleSeconds -->  当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空;即缓存被创建后,最后一次访问时间到缓存失效之时,两者之间的间隔,单位为秒(s)

  timeToLiveSeconds必须大于timeToIdleSeconds才有意义。

 

测试代码:

package encache;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class FirstCache {
    private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());

    // 1.创建CacheManager
//    CacheManager cacheManager = CacheManager.create("E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml");// 也可以通过URL制定
    //一般用下面这种方式创建Cachemanager
//    CacheManager cacheManager = CacheManager.create();//默认读取classpath目录下面的ehcache.xml
     CacheManager cacheManager = new  CacheManager();//默认读取classpath目录下面的ehcache.xml

    public FirstCache() {
        // 2.创建Cache
        Cache cache = cacheManager.getCache("cache_test");
        // 3.存取元素
        cache.put(new Element("firstCache", "第一个缓存元素"));

        // 4.获取元素
        Element element = cache.get("firstCache");
        log.info("获取的缓存元素是:{}", element);
        long creationTime = element.getCreationTime();
        long expirationTime = element.getExpirationTime();
        log.info("creationTime: {}", new Date(creationTime));
        log.info("expirationTime: {}", new Date(expirationTime));

        int diskStoreSize = cache.getDiskStoreSize();
        int cacheSize = cache.getKeys().size();
        log.info("diskStoreSize:{}", diskStoreSize);
        log.info("cacheSize: {}", cacheSize);
    }

    public static void main(String[] args) throws Exception {
        new FirstCache();
    }
}

 

 

 结果:(注意存活时间是60s,注意标红的信息)

2018-09-09 14:45:57 [net.sf.ehcache.CacheManager]-[DEBUG] Configuring ehcache from classpath.
2018-09-09 14:45:57 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from ehcache.xml found in the classpath: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
2018-09-09 14:45:57 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from URL: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
2018-09-09 14:45:57 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from InputStream
2018-09-09 14:45:58 [net.sf.ehcache.config.DiskStoreConfiguration]-[DEBUG] Disk Store Path: C:\Users\liqiang\AppData\Local\Temp\
2018-09-09 14:45:58 [net.sf.ehcache.util.PropertyUtil]-[DEBUG] propertiesString is null.
2018-09-09 14:45:58 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheManagerEventListenerFactory class specified. Skipping...
2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
2018-09-09 14:45:59 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
2018-09-09 14:45:59 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
2018-09-09 14:45:59 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for cache_test
2018-09-09 14:45:59 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.data
2018-09-09 14:45:59 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
2018-09-09 14:45:59 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\cache_test.index
2018-09-09 14:45:59 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
2018-09-09 14:45:59 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: cache_test
2018-09-09 14:45:59 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured. Skipping for 'cache_test'.
2018-09-09 14:45:59 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache_test'.
2018-09-09 14:45:59 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
2018-09-09 14:45:59 [encache.FirstCache]-[INFO] 获取的缓存元素是:[ key = firstCache, value=第一个缓存元素, version=1, hitCount=1, CreationTime = 1536475559759, LastAccessTime = 1536475559799 ]
2018-09-09 14:45:59 [encache.FirstCache]-[INFO] creationTime: Sun Sep 09 14:45:59 CST 2018
2018-09-09 14:45:59 [encache.FirstCache]-[INFO] expirationTime: Sun Sep 09 14:46:59 CST 2018
2018-09-09 14:45:59 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
2018-09-09 14:45:59 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
2018-09-09 14:45:59 [encache.FirstCache]-[INFO] diskStoreSize:0
2018-09-09 14:45:59 [encache.FirstCache]-[INFO] cacheSize: 1

 

并且在:C:\Users\liqiang\AppData\Local\Temp文件夹下面生成一个cache_test.data的文件。

 

 

删除缓存只需要采用如下方法:

        // 4.删除一个元素
        cache.remove("key");

 

 

 

2.获取缓存配置

package encache;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;

public class FirstCache {
    private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());

    // 1.创建CacheManager
    CacheManager cacheManager = new CacheManager();// 默认读取classpath目录下面的ehcache.xml

    public FirstCache() {
        // 2.创建Cache
        Cache cache = cacheManager.getCache("cache_test");
        CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
        // 2.1获取满了之后的清除策略
        MemoryStoreEvictionPolicy policy = cacheConfiguration.getMemoryStoreEvictionPolicy();
        log.info("{}", cacheConfiguration.getDiskStorePath());
        log.info("{}", cacheConfiguration.getTimeToIdleSeconds());
        log.info("{}", cacheConfiguration.getTimeToLiveSeconds());
        log.info("{}", cacheConfiguration.getMaxElementsInMemory());
        log.info("{}", cacheConfiguration.getMaxElementsOnDisk());
        log.info("{}", cacheConfiguration.getName());
        log.info("{}", policy.toString());
    }

    public static void main(String[] args) throws Exception {
        new FirstCache();
    }
}

 

结果:

2018-09-09 15:08:14 [encache.FirstCache]-[INFO] null
2018-09-09 15:08:14 [encache.FirstCache]-[INFO] 60
2018-09-09 15:08:14 [encache.FirstCache]-[INFO] 60
2018-09-09 15:08:14 [encache.FirstCache]-[INFO] 2
2018-09-09 15:08:14 [encache.FirstCache]-[INFO] 2
2018-09-09 15:08:14 [encache.FirstCache]-[INFO] cache_test
2018-09-09 15:08:14 [encache.FirstCache]-[INFO] FIFO

 

3.动态的修改缓存的配置:

代码:

        cacheConfiguration.setDiskStorePath(System.getProperty("java.io.tmpdir"));
        cacheConfiguration.setTimeToIdleSeconds(200);
        cacheConfiguration.setTimeToLiveSeconds(200);
        cacheConfiguration.setMaxElementsInMemory(4);
        cacheConfiguration.setMaxElementsOnDisk(4);
        cacheConfiguration.setName("cache_test_update");
        cacheConfiguration.setMemoryStoreEvictionPolicy("CLOCK");

 

直接修改会报错:

Exception in thread "main" net.sf.ehcache.CacheException: Dynamic configuration changes are disabled for this cache
at net.sf.ehcache.config.CacheConfiguration.checkDynamicChange(CacheConfiguration.java:2711)
at net.sf.ehcache.config.CacheConfiguration.setDiskStorePath(CacheConfiguration.java:948)
at encache.FirstCache.<init>(FirstCache.java:35)
at encache.FirstCache.main(FirstCache.java:53)

 

官方解释:原因是上面encache.xml阻止了动态修改cache配置

Dynamic cache configurations can also be frozen to prevent future changes:
  Cache cache = manager.getCache("sampleCache");
  cache.disableDynamicFeatures();
In ehcache.xml, you can disable dynamic configuration by setting the <ehcache> element's
  dynamicConfig attribute to "false".

 

 

解决办法在官方解释中说了,修改dynamicConfig属性为true

 <ehcache updateCheck="false" dynamicConfig="true">  
    <diskStore path="java.io.tmpdir"/>  
    
    <defaultCache  
        maxElementsInMemory="1000"  
        eternal="false"  
        overflowToDisk="true"  
        timeToIdleSeconds="120"  
        timeToLiveSeconds="120"  
        diskPersistent="false"  
        diskExpiryThreadIntervalSeconds="120"  
        memoryStoreEvictionPolicy="LRU"
    />      
     
    <cache name="cache_test" 
        maxElementsInMemory="2"  
        eternal="false"  
        timeToIdleSeconds="60"  
        timeToLiveSeconds="60"  
        maxElementsOnDisk="2"
        overflowToDisk="true"
        diskPersistent="false" 
        memoryStoreEvictionPolicy="FIFO"  
   />   
</ehcache> 

 

 

修改之后再次执行下main代码:

    public FirstCache() {
        // 2.创建Cache
        Cache cache = cacheManager.getCache("cache_test");
        CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
        // 2.1获取满了之后的清除策略
        MemoryStoreEvictionPolicy policy = cacheConfiguration.getMemoryStoreEvictionPolicy();
        log.info("{}", cacheConfiguration.getDiskStorePath());
        log.info("{}", cacheConfiguration.getTimeToIdleSeconds());
        log.info("{}", cacheConfiguration.getTimeToLiveSeconds());
        log.info("{}", cacheConfiguration.getMaxElementsInMemory());
        log.info("{}", cacheConfiguration.getMaxElementsOnDisk());
        log.info("{}", cacheConfiguration.getName());
        log.info("{}", policy.toString());
        log.info("===============================");
        
        cacheConfiguration.setDiskStorePath(System.getProperty("java.io.tmpdir"));
        cacheConfiguration.setTimeToIdleSeconds(200);
        cacheConfiguration.setTimeToLiveSeconds(200);
        cacheConfiguration.setMaxElementsInMemory(4);
        cacheConfiguration.setMaxElementsOnDisk(4);
        cacheConfiguration.setName("cache_test_update");
        cacheConfiguration.setMemoryStoreEvictionPolicy("CLOCK");
        MemoryStoreEvictionPolicy policy2 = cacheConfiguration.getMemoryStoreEvictionPolicy();
        log.info("{}", cacheConfiguration.getDiskStorePath());
        log.info("{}", cacheConfiguration.getTimeToIdleSeconds());
        log.info("{}", cacheConfiguration.getTimeToLiveSeconds());
        log.info("{}", cacheConfiguration.getMaxElementsInMemory());
        log.info("{}", cacheConfiguration.getMaxElementsOnDisk());
        log.info("{}", cacheConfiguration.getName());
        log.info("{}", policy2.toString());
    }

 

结果:(修改生效)

2018-09-09 15:18:46 [encache.FirstCache]-[INFO] null
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 60
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 60
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 2
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 2
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] cache_test
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] FIFO
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] ===============================
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] C:\Users\liqiang\AppData\Local\Temp\
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 200
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 200
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 4
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] 4
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] cache_test_update
2018-09-09 15:18:46 [encache.FirstCache]-[INFO] CLOCK

 

 

4.测试上面配置的一些作用:

修改上面的配置:

    <cache name="cache_test" 
        maxElementsInMemory="2"  
        eternal="false"  
        timeToIdleSeconds="5"  
        timeToLiveSeconds="5"  
        maxElementsOnDisk="2"
        overflowToDisk="true"
        diskPersistent="false" 
        memoryStoreEvictionPolicy="FIFO"  
   />   

 

 

(1)测试缓存的生存时间:

package encache;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class FirstCache {
    private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());

    public FirstCache() {

        // 1.创建CacheManager
        CacheManager cacheManager = new CacheManager();// 默认读取classpath目录下面的ehcache.xml

        // 2.创建Cache
        Cache cache = cacheManager.getCache("cache_test");

        // 3.存取元素
        cache.put(new Element("firstCache", "第一个缓存元素"));

        // 4.获取元素
        Element element = cache.get("firstCache");
        log.info("获取的缓存元素是:{}", element);
        long creationTime = element.getCreationTime();
        long expirationTime = element.getExpirationTime();
        log.info("creationTime: {}", new Date(creationTime));
        log.info("expirationTime: {}", new Date(expirationTime));
        log.info("diskStoreSize:{}", cache.getDiskStoreSize());
        log.info("cacheSize: {}", cache.getKeys().size());

        // 线程休眠6s,使缓存超时
        try {
            // Thread.sleep(6*1000);
            TimeUnit.SECONDS.sleep(7);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // 再次获取元素
        try {
            Element element1 = cache.get("firstCache");
            long creationTime1 = element1.getCreationTime();
            long expirationTime1 = element1.getExpirationTime();
            log.info("creationTime1: {}", new Date(creationTime1));
            log.info("expirationTime1: {}", new Date(expirationTime1));
        } catch (Exception e) {
            log.error("元素不存在");
        } finally {
            log.info("diskStoreSize:{}", cache.getDiskStoreSize());
            log.info("cacheSize: {}", cache.getKeys().size());
        }
    }

    public static void main(String[] args) throws Exception {
        new FirstCache();
    }
}

 

查看日志:

2018-09-09 15:45:55 [net.sf.ehcache.CacheManager]-[DEBUG] Configuring ehcache from classpath.
2018-09-09 15:45:55 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from ehcache.xml found in the classpath: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
2018-09-09 15:45:55 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from URL: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
2018-09-09 15:45:55 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from InputStream
2018-09-09 15:45:55 [net.sf.ehcache.config.DiskStoreConfiguration]-[DEBUG] Disk Store Path: C:\Users\liqiang\AppData\Local\Temp\
2018-09-09 15:45:55 [net.sf.ehcache.util.PropertyUtil]-[DEBUG] propertiesString is null.
2018-09-09 15:45:55 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheManagerEventListenerFactory class specified. Skipping...
2018-09-09 15:45:56 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
2018-09-09 15:45:56 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
2018-09-09 15:45:56 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
2018-09-09 15:45:56 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
2018-09-09 15:45:56 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
2018-09-09 15:45:56 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
2018-09-09 15:45:56 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for cache_test
2018-09-09 15:45:56 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.data
2018-09-09 15:45:56 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
2018-09-09 15:45:57 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\cache_test.index
2018-09-09 15:45:57 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
2018-09-09 15:45:57 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: cache_test
2018-09-09 15:45:57 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured. Skipping for 'cache_test'.
2018-09-09 15:45:57 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache_test'.
2018-09-09 15:45:57 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
2018-09-09 15:45:57 [encache.FirstCache]-[INFO] 获取的缓存元素是:[ key = firstCache, value=第一个缓存元素, version=1, hitCount=1, CreationTime = 1536479157042, LastAccessTime = 1536479157054 ]
2018-09-09 15:45:57 [encache.FirstCache]-[INFO] creationTime: Sun Sep 09 15:45:57 CST 2018
2018-09-09 15:45:57 [encache.FirstCache]-[INFO] expirationTime: Sun Sep 09 15:46:02 CST 2018
2018-09-09 15:45:57 [encache.FirstCache]-[INFO] diskStoreSize:0
2018-09-09 15:45:57 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
2018-09-09 15:45:57 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
2018-09-09 15:45:57 [encache.FirstCache]-[INFO] cacheSize: 1
2018-09-09 15:46:04 [net.sf.ehcache.store.disk.Segment]-[DEBUG] remove deleted 0 from heap
2018-09-09 15:46:04 [net.sf.ehcache.store.disk.Segment]-[DEBUG] remove deleted 0 from disk
2018-09-09 15:46:04 [encache.FirstCache]-[ERROR] 元素不存在
2018-09-09 15:46:04 [encache.FirstCache]-[INFO] diskStoreSize:0
2018-09-09 15:46:04 [encache.FirstCache]-[INFO] cacheSize: 0

 

也就是6s之后缓存会自动清除。缓存时间生效。

 

(2)测试缓存对象数量问题:

package encache;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class FirstCache {
    private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());

    public FirstCache() {

        // 1.创建CacheManager
        CacheManager cacheManager = new CacheManager();// 默认读取classpath目录下面的ehcache.xml

        // 2.创建Cache
        Cache cache = cacheManager.getCache("cache_test");

        // 3.存取5个元素
        cache.put(new Element("1", "第1个缓存元素"));
        cache.put(new Element("2", "第2个缓存元素"));
        cache.put(new Element("3", "第3个缓存元素"));
        cache.put(new Element("4", "第4个缓存元素"));
        cache.put(new Element("5", "第5个缓存元素"));
        cache.flush();

        try {
            Thread.sleep(2 * 1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        log.info("diskStoreSize:{}", cache.getDiskStoreSize());
        log.info("cacheSize: {}", cache.getKeys().size());
        // 4.获取元素
        for (Object key : cache.getKeys()) {
            log.info("ele:{}", cache.get(key).toString());
        }

    }

    public static void main(String[] args) throws Exception {
        new FirstCache();
    }
}

 

结果:(只获取到最后添加的两个元素。FIFO策略也生效)

2018-09-09 16:17:11 [net.sf.ehcache.CacheManager]-[DEBUG] Configuring ehcache from classpath.
2018-09-09 16:17:11 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from ehcache.xml found in the classpath: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
2018-09-09 16:17:11 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from URL: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
2018-09-09 16:17:11 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from InputStream
2018-09-09 16:17:11 [net.sf.ehcache.config.DiskStoreConfiguration]-[DEBUG] Disk Store Path: C:\Users\liqiang\AppData\Local\Temp\
2018-09-09 16:17:11 [net.sf.ehcache.util.PropertyUtil]-[DEBUG] propertiesString is null.
2018-09-09 16:17:11 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheManagerEventListenerFactory class specified. Skipping...
2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
2018-09-09 16:17:13 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
2018-09-09 16:17:13 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
2018-09-09 16:17:13 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for cache_test
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\cache_test.index
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
2018-09-09 16:17:13 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: cache_test
2018-09-09 16:17:13 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured. Skipping for 'cache_test'.
2018-09-09 16:17:13 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache_test'.
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] put added 0 on heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from disk
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from disk
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault removed 0 from heap
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] fault added 0 on disk
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from disk
2018-09-09 16:17:13 [net.sf.ehcache.store.disk.Segment]-[DEBUG] evicted 0 from heap
2018-09-09 16:17:15 [encache.FirstCache]-[INFO] diskStoreSize:2
2018-09-09 16:17:15 [encache.FirstCache]-[INFO] cacheSize: 2
2018-09-09 16:17:15 [encache.FirstCache]-[INFO] ele:[ key = 5, value=第5个缓存元素, version=1, hitCount=1, CreationTime = 1536481034000, LastAccessTime = 1536481035344 ]
2018-09-09 16:17:15 [encache.FirstCache]-[INFO] ele:[ key = 4, value=第4个缓存元素, version=1, hitCount=1, CreationTime = 1536481034000, LastAccessTime = 1536481035347 ]

 

 

3.defaultCache的作用

  一直以为defaultCache的配置是会给我们创建一个cache,实际上是在程序中创建的cache会默认采用此配置。

 

在encache-core的包下面的ehcache-failsafe.xml的描述如下:

    <!--
    Mandatory Default Cache configuration. These settings will be applied to caches
    created programmtically using CacheManager.add(String cacheName)
    -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />

 

 

也就是程序中显示创建的Cache会默认使用defaultCache的配置。

 

package encache;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;

public class FirstCache {
    private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());

    public FirstCache() {

        // 1.创建CacheManager
        CacheManager cacheManager = CacheManager.create();

        // 2.创建并且获取Cache
        cacheManager.addCache("dynamic_cache");
        Cache cache = cacheManager.getCache("dynamic_cache");
        CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
        // 2.1获取满了之后的清除策略
        MemoryStoreEvictionPolicy policy = cacheConfiguration.getMemoryStoreEvictionPolicy();
        log.info("{}", cacheConfiguration.getDiskStorePath());
        log.info("{}", cacheConfiguration.getTimeToIdleSeconds());
        log.info("{}", cacheConfiguration.getTimeToLiveSeconds());
        log.info("{}", cacheConfiguration.getMaxElementsInMemory());
        log.info("{}", cacheConfiguration.getMaxElementsOnDisk());
        log.info("{}", cacheConfiguration.getName());
        log.info("{}", policy.toString());

    }

    public static void main(String[] args) throws Exception {
        new FirstCache();
    }
}

 

结果:

2018-09-09 16:51:27 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from ehcache.xml found in the classpath: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
2018-09-09 16:51:27 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from URL: file:/E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml
2018-09-09 16:51:27 [net.sf.ehcache.config.ConfigurationFactory]-[DEBUG] Configuring ehcache from InputStream
2018-09-09 16:51:27 [net.sf.ehcache.config.DiskStoreConfiguration]-[DEBUG] Disk Store Path: C:\Users\liqiang\AppData\Local\Temp\
2018-09-09 16:51:27 [net.sf.ehcache.CacheManager]-[DEBUG] Creating new CacheManager with default config
2018-09-09 16:51:27 [net.sf.ehcache.util.PropertyUtil]-[DEBUG] propertiesString is null.
2018-09-09 16:51:27 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheManagerEventListenerFactory class specified. Skipping...
2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] No BootstrapCacheLoaderFactory class specified. Skipping...
2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] CacheWriter factory not configured. Skipping...
2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] No CacheExceptionHandlerFactory class specified. Skipping...
2018-09-09 16:51:29 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for cache_test
2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\cache_test.index
2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file cache_test.index
2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: cache_test
2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured. Skipping for 'cache_test'.
2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache_test'.
2018-09-09 16:51:29 [net.sf.ehcache.store.MemoryStore]-[DEBUG] Initialized net.sf.ehcache.store.MemoryStore for dynamic_cache
2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file dynamic_cache.data
2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file dynamic_cache.index
2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Matching data file missing (or empty) for index file. Deleting index file C:\Users\liqiang\AppData\Local\Temp\dynamic_cache.index
2018-09-09 16:51:29 [net.sf.ehcache.store.disk.DiskStorageFactory]-[DEBUG] Failed to delete file dynamic_cache.index
2018-09-09 16:51:29 [net.sf.ehcache.Cache]-[DEBUG] Initialised cache: dynamic_cache
2018-09-09 16:51:29 [net.sf.ehcache.config.ConfigurationHelper]-[DEBUG] CacheDecoratorFactory not configured for defaultCache. Skipping for 'dynamic_cache'.
2018-09-09 16:51:29 [encache.FirstCache]-[INFO] null
2018-09-09 16:51:29 [encache.FirstCache]-[INFO] 120
2018-09-09 16:51:29 [encache.FirstCache]-[INFO] 120
2018-09-09 16:51:29 [encache.FirstCache]-[INFO] 1000
2018-09-09 16:51:29 [encache.FirstCache]-[INFO] 0
2018-09-09 16:51:29 [encache.FirstCache]-[INFO] dynamic_cache
2018-09-09 16:51:29 [encache.FirstCache]-[INFO] LRU

 

4.encache原码分析:

CacheManager

  一个普通的class,里面包含管理cache的信息

public class CacheManager {

    /**
     * Default name if not specified in the configuration/
     */
    public static final String DEFAULT_NAME = "__DEFAULT__";

    /**
     * Threshold, in percent of the available heap, above which the CacheManager will warn if the configured memory
     */
    public static final double ON_HEAP_THRESHOLD = 0.8;

    /**
     * Keeps track of all known CacheManagers. Used to check on conflicts.
     * CacheManagers should remove themselves from this list during shut down.
     */
    public static final List<CacheManager> ALL_CACHE_MANAGERS = new CopyOnWriteArrayList<CacheManager>();

    /**
     * System property to enable creation of a shutdown hook for CacheManager.
     */
    public static final String ENABLE_SHUTDOWN_HOOK_PROPERTY = "net.sf.ehcache.enableShutdownHook";

    private static final Logger LOG = LoggerFactory.getLogger(CacheManager.class);

    /**
     * Update check interval - one week in milliseconds
     */
    private static final long EVERY_WEEK = 7 * 24 * 60 * 60 * 1000;

  
    private static final long DELAY_UPDATE_CHECK = 1000;

   
    private static volatile CacheManager singleton;


    private static final MBeanRegistrationProviderFactory MBEAN_REGISTRATION_PROVIDER_FACTORY = new MBeanRegistrationProviderFactoryImpl();

    private static final String NO_DEFAULT_CACHE_ERROR_MSG = "Caches cannot be added by name when default cache config is not specified"
            + " in the config. Please add a default cache config in the configuration.";

    private static final Map<String, CacheManager> CACHE_MANAGERS_MAP = new HashMap<String, CacheManager>();

    private static final IdentityHashMap<CacheManager, String> CACHE_MANAGERS_REVERSE_MAP = new IdentityHashMap<CacheManager, String>();


    protected volatile Status status;

    protected final Map<String, CacheManagerPeerProvider> cacheManagerPeerProviders = new ConcurrentHashMap<String, CacheManagerPeerProvider>();

 
    protected final Map<String, CacheManagerPeerListener> cacheManagerPeerListeners = new ConcurrentHashMap<String, CacheManagerPeerListener>();

    
    protected final CacheManagerEventListenerRegistry cacheManagerEventListenerRegistry = new CacheManagerEventListenerRegistry();

    
    protected Thread shutdownHook;


    private final ConcurrentMap<String, Ehcache> ehcaches = new ConcurrentHashMap<String, Ehcache>();

 ehcaches里面存放的是一个一个的cache。

 

Cache:

public class Cache implements InternalEhcache, StoreListener {


    public static final String DEFAULT_CACHE_NAME = "default";


    public static final String NET_SF_EHCACHE_DISABLED = "net.sf.ehcache.disabled";


    public static final String NET_SF_EHCACHE_USE_CLASSIC_LRU = "net.sf.ehcache.use.classic.lru";


    public static final long DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = CacheConfiguration.DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS;


    public static final String OFF_HEAP_STORE_CLASSNAME = "net.sf.ehcache.store.offheap.OffHeapStore";

    private static final Logger LOG = LoggerFactory.getLogger(Cache.class.getName());

 private volatile Store compoundStore; 用于存放真正的元素。

 

Element:

  一个实现serializable和clonable的普通类,里面有key和value以及一些其他信息:

public class Element implements Serializable, Cloneable {

    private static final long serialVersionUID = 1098572221246444544L;

    private static final Logger LOG = LoggerFactory.getLogger(Element.class.getName());

    private static final AtomicLongFieldUpdater<Element> HIT_COUNT_UPDATER = AtomicLongFieldUpdater.newUpdater(Element.class, "hitCount");

    private static final boolean ELEMENT_VERSION_AUTO = Boolean.getBoolean("net.sf.ehcache.element.version.auto");

    static {
        if (ELEMENT_VERSION_AUTO) {
            LOG.warn("Note that net.sf.ehcache.element.version.auto is set and user provided version will not be honored");
        }
    }


    @IgnoreSizeOf
    private final Object key;


    private final Object value;


    private volatile long version;


    private volatile long hitCount;


    private volatile int timeToLive = Integer.MIN_VALUE;

    private volatile int timeToIdle = Integer.MIN_VALUE;


    private transient volatile ElementEvictionData elementEvictionData;


    private volatile long lastUpdateTime;

    private volatile boolean cacheDefaultLifespan = true;

 

  Encache也可以进行集群等高级操作,待用到的时候查阅API即可。encache是新开一个线程进行缓存管理,JVM不停此线程也不会停止。

 

补充:在一个JVM如果创建两个名字相同的cache,则会报错,如下:

package encache;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.ehcache.CacheManager;

public class SecondCache {
    private static final Logger log = LoggerFactory.getLogger(SecondCache.class.getName());

    public static void main(String[] args) throws Exception {
        // 1.创建CacheManager
        final CacheManager cacheManager = CacheManager.create();
        new Thread(new Runnable() {
            @Override
            public void run() {
                cacheManager.addCache("dynamic_cache");
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                cacheManager.addCache("dynamic_cache");
            }
        }).start();
    }
}

 

结果:

Exception in thread "Thread-1" net.sf.ehcache.ObjectExistsException: Cache dynamic_cache already exists
at net.sf.ehcache.CacheManager.addCacheNoCheck(CacheManager.java:1294)
at net.sf.ehcache.CacheManager.addCache(CacheManager.java:1184)
at net.sf.ehcache.CacheManager.addCache(CacheManager.java:1126)
at encache.SecondCache$1.run(SecondCache.java:17)
at java.lang.Thread.run(Thread.java:745)

 

补充:Element有一个构造方法可以指定缓存的时间等参数

package encache;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class FirstCache {
    private static final Logger log = LoggerFactory.getLogger(FirstCache.class.getName());

    public FirstCache() {

        // 1.创建CacheManager
        CacheManager cacheManager = new CacheManager();// 默认读取classpath目录下面的ehcache.xml

        // 2.创建Cache
        Cache cache = cacheManager.getCache("cache_test");

        // 3.添加元素
        cache.put(new Element("key", "value", false, 0, 12));

        // 4.休眠5秒钟获取元素
        try {
            Thread.sleep(5 * 1000);
        } catch (InterruptedException e) {
        }
        Element element = cache.get("key");
        System.out.println(element);

        // 4.休眠13秒钟获取元素
        try {
            Thread.sleep(13 * 1000);
        } catch (InterruptedException e) {
        }
        // 4.获取元素
        Element element2 = cache.get("key");
        System.out.println(element2);

    }

    public static void main(String[] args) throws Exception {
        new FirstCache();
    }
}

 

结果:

[ key = key, value=value, version=0, hitCount=1, CreationTime = 1544537618418, LastAccessTime = 1544537623428 ]
null

 

补充:在学习了多线程之后对ehcache缓存进行的实验多线程环境下

package encache;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class SecondCache {
    private static final Logger log = LoggerFactory.getLogger(SecondCache.class.getName());

    public static void main(String[] args) throws Exception {
        // 1.创建CacheManager
        final CacheManager cacheManager = CacheManager.create();
        // 开启线程创建cache
        new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("添加缓存->{},threadName->{}", "dynamic_cache", Thread.currentThread().getName());
                cacheManager.addCache("dynamic_cache");
            }
        }, "A").start();
        // 添加元素
        Thread.sleep(1 * 1000);
        new Thread(new Runnable() {
            @Override
            public void run() {
                Cache cache = cacheManager.getCache("dynamic_cache");
                for (int i = 0; i < 5; i++) {
                    Map<String, Object> cacheEle = new HashMap<>();
                    cacheEle.put("" + i, "第" + i + "个元素");
                    log.info("添加缓存元素->{},threadName->{}", cacheEle, Thread.currentThread().getName());
                    cache.put(new Element(i + "key", cacheEle));
                }

                // 覆盖第二个元素
                Map<String, Object> cacheEle = new HashMap<>();
                cacheEle.put("" + 2, "第" + 22222 + "个元素");
                cache.put(new Element(2 + "key", cacheEle));
                log.info("覆盖缓存元素->{},threadName->{}", 2 + "key", Thread.currentThread().getName());
                cache.flush();
            }
        }, "B").start();
        // 访问元素
        Thread.sleep(1 * 1000);
        new Thread(new Runnable() {
            @Override
            public void run() {
                Cache cache = cacheManager.getCache("dynamic_cache");
                for (Object key : cache.getKeys()) {
                    log.info("获取缓存元素key->{},value->{},threadName->{}", new Object[] { key,
                            (Map) cache.get(key).getObjectValue(), Thread.currentThread().getName() });
                }
            }
        }, "C").start();

    }
}

 

结果:

2018-12-11 21:53:10 [encache.SecondCache]-[INFO] 添加缓存->dynamic_cache,threadName->A
2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{0=第0个元素},threadName->B
2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{1=第1个元素},threadName->B
2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{2=第2个元素},threadName->B
2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{3=第3个元素},threadName->B
2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 添加缓存元素->{4=第4个元素},threadName->B
2018-12-11 21:53:11 [encache.SecondCache]-[INFO] 覆盖缓存元素->2key,threadName->B
2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->4key,value->{4=第4个元素},threadName->C
2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->1key,value->{1=第1个元素},threadName->C
2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->3key,value->{3=第3个元素},threadName->C
2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->0key,value->{0=第0个元素},threadName->C
2018-12-11 21:53:12 [encache.SecondCache]-[INFO] 获取缓存元素key->2key,value->{2=第22222个元素},threadName->C

 

补充:自己封装的一个工具类以及简单的测试:

package ehcache;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;

public class EhcacheUtils {
    public static final String CACHE_NAME1 = "cache1";
    public static final String CACHE_NAME2 = "cache2";

    public static final int CACHE_ONE_HOUR = 1 * 60 * 60;
    public static final int CACHE_ONE_DAY = 24 * 60 * 60;

    private static CacheManager cacheManager = CacheManager.create();
    // 静态代码块创建缓存
    static {
        cacheManager.addCache(CACHE_NAME1);
        cacheManager.addCache(CACHE_NAME2);

        initCacheSettings(cacheManager.getCache(CACHE_NAME1));
        initCacheSettings(cacheManager.getCache(CACHE_NAME2));
    }

    private static void initCacheSettings(Cache cache) {
        CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
        cacheConfiguration.setTimeToIdleSeconds(8 * 60 * 60);
        cacheConfiguration.setTimeToLiveSeconds(24 * 60 * 60);
        // cacheConfiguration.setMaxElementsInMemory(4);
        // cacheConfiguration.setMaxElementsOnDisk(4);
        // cacheConfiguration.setName("cache_test_update");
        cacheConfiguration.setMemoryStoreEvictionPolicy("CLOCK");
    }

    private EhcacheUtils() {

    }

    // 1.增加元素
    /**
     * 向指定的缓存中增加元素
     * 
     * @param cacheName
     *            缓存名称
     * @param key
     *            缓存的key
     * @param value
     *            缓存d值
     * @param seconds
     *            缓存的时间(秒)
     * @param override
     *            如果存在是否覆盖
     * @return
     */
    public static boolean addCache(String cacheName, String key, Object value, int seconds, boolean override) {
        try {
            Cache cache = cacheManager.getCache(cacheName);
            Object tmpValue = getValueByCacheKey(cacheName, key);
            if (tmpValue != null) {
                if (!override) {
                    return true;
                }
            }
            cache.put(new Element(key, value, false, 0, seconds));
            cache.flush();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    // 2.删除元素
    // 2.1删除单个元素
    /**
     * 删除单个元素
     * 
     * @param cacheName
     *            缓存的名称
     * @param key
     *            缓存的key
     * @return
     */
    public static boolean removeCacheByKey(String cacheName, String key) {
        try {
            Cache cache = cacheManager.getCache(cacheName);
            cache.remove(key);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    // 2.2删除全部元素
    /**
     * 删除所有元素
     * 
     * @param cacheName
     *            缓存名称
     * @return
     */
    public static boolean removeAllByCacheName(String cacheName) {
        try {
            Cache cache = cacheManager.getCache(cacheName);
            cache.removeAll();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    // 3.获取元素
    // 3.1获取单个元素
    /**
     * 获取单个元素
     * 
     * @param cacheName
     *            缓存名称
     * @param key
     *            缓存的key
     * @return
     */
    public static Object getValueByCacheKey(String cacheName, String key) {
        try {
            Cache cache = cacheManager.getCache(cacheName);
            Element element = cache.get(key);
            return element == null ? null : element.getObjectValue();
        } catch (Exception e) {
            return null;
        }
    }

    // 3.1获取全部元素
    /**
     * 获取所有缓存d元素
     * 
     * @param cacheName
     *            缓存的名称
     * @return
     */
    public static List<Object> getAllValuesByCacheName(String cacheName) {
        List<Object> result = new ArrayList<Object>();
        try {
            Cache cache = cacheManager.getCache(cacheName);
            for (Object key : cache.getKeys()) {
                Element element = cache.get(key);
                result.add(element.getObjectValue());
            }
            return result;
        } catch (Exception e) {
            return result;
        }
    }

    // 4.获取配置
    public static Map<String, String> getConfigurations(String cacheName) {
        Map<String, String> results = new HashMap<String, String>();
        Cache cache = cacheManager.getCache(cacheName);
        CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();

        MemoryStoreEvictionPolicy policy = cacheConfiguration.getMemoryStoreEvictionPolicy();
        results.put("timeToIdleSeconds", String.valueOf(cacheConfiguration.getTimeToIdleSeconds()));
        results.put("timeToLiveSeconds", String.valueOf(cacheConfiguration.getTimeToLiveSeconds()));
        results.put("maxElementsInMemory", String.valueOf(cacheConfiguration.getMaxElementsInMemory()));
        results.put("policy", policy.toString());
        return results;
    }
}

 ehcache.xml

<ehcache updateCheck="false" dynamicConfig="true">  
    <diskStore path="java.io.tmpdir"/>  
    
    <defaultCache  
        maxElementsInMemory="1000"  
        eternal="false"  
        overflowToDisk="true"  
        timeToIdleSeconds="120"  
        timeToLiveSeconds="120"  
        diskPersistent="false"  
        diskExpiryThreadIntervalSeconds="120"  
        memoryStoreEvictionPolicy="LRU"
    />      
</ehcache>

 

测试代码:

        List<String> cache1 = new ArrayList<>();
        cache1.add("111");
        cache1.add("222");

        EhcacheUtils.addCache(EhcacheUtils.CACHE_NAME1, "cache1", cache1, EhcacheUtils.CACHE_ONE_HOUR, false);

        String cache2 = "cache2";
        EhcacheUtils.addCache(EhcacheUtils.CACHE_NAME1, "cache2", cache2, EhcacheUtils.CACHE_ONE_HOUR, false);

        Map cache3 = new HashMap();
        cache3.put("1", "111222");
        cache3.put("2", "111222333");
        EhcacheUtils.addCache(EhcacheUtils.CACHE_NAME1, "cache3", cache3, EhcacheUtils.CACHE_ONE_HOUR, false);

        Map valueByCacheKey = (Map) EhcacheUtils.getValueByCacheKey(EhcacheUtils.CACHE_NAME1, "cache3");
        System.out.println(valueByCacheKey);

        EhcacheUtils.removeCacheByKey(EhcacheUtils.CACHE_NAME1, "cache2");
        List<Object> allValuesByCacheName = EhcacheUtils.getAllValuesByCacheName(EhcacheUtils.CACHE_NAME1);
        for (Object obj : allValuesByCacheName) {
            System.out.println(obj);
        }

        Map<String, String> configurations = EhcacheUtils.getConfigurations(EhcacheUtils.CACHE_NAME1);
        System.out.println(configurations);

结果:(线程也没有停止)

 

采用JVisualVM查看线程信息: (主线程结束了,但是仍然有ehcache创建的用户线程,有3个用户线程----创建CacheManager的时候会创建一个守护线程Statisxxxx,每次创建一个cache的时候也会创建一个用户线程 cacheName.data)

 

源代码跟踪解释线程:

(1)在  调用CacheManager cacheManager = CacheManager.create();   创建CacheManager的时候创建一个守护线程Statistics thread-_default_-1  统计线程

    public CacheManager(String configurationFileName) throws CacheException {
        status = Status.STATUS_UNINITIALISED;
        init(null, configurationFileName, null, null);
    }

 

 

init中调用doInit(...)

 

doInit(...)创建线程(用到线程池进行周期性调用---此线程是一个守护线程)

        statisticsExecutor = Executors.newScheduledThreadPool(
          Integer.getInteger("net.sf.ehcache.CacheManager.statisticsExecutor.poolSize", 1) ,

          new ThreadFactory() {
             private AtomicInteger cnt = new AtomicInteger(0);
             @Override
             public Thread newThread(Runnable r) {
                Thread t = new Thread(r, "Statistics Thread-" + getName() + "-" + cnt.incrementAndGet());
                t.setDaemon(true);
                return t;
             }
          });

 

 

(2)在调用cacheManager.addCache("cache1");的时候创建一个用户线程:cache1.data (所以主线程结束,此线程也没有结束,进程也没有结束)

        ...这个代码暂时没有根出来,只是根到调用此方法后创建了一个用户线程

 

最完美的就是再写一个key生成器,KeyGenerator可以参考下面代码:

package cn.xm.jwxt.utils;

import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @Author: qlq
 * @Description
 * @Date: 22:49 2018/3/25
 */
public class KeyGenerator implements org.springframework.cache.interceptor.KeyGenerator {
    @Override
    public Object generate(Object o, Method method, Object... params) {
        //规定  本类名+方法名+参数名 为key
        StringBuilder sb = new StringBuilder();
        sb.append(o.getClass().getName());
        sb.append(method.getName());
        for (Object param : params) {
            sb.append(param.toString());
        }
        return sb.toString();
    }
}

 

posted @ 2018-09-09 12:14  QiaoZhi  阅读(7326)  评论(0编辑  收藏  举报