zoukankan      html  css  js  c++  java
  • 【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:UsersliqiangAppDataLocalTemp
    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:UsersliqiangAppDataLocalTempcache_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:UsersliqiangAppDataLocalTemp文件夹下面生成一个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:UsersliqiangAppDataLocalTemp
    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:UsersliqiangAppDataLocalTemp
    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:UsersliqiangAppDataLocalTempcache_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:UsersliqiangAppDataLocalTemp
    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:UsersliqiangAppDataLocalTempcache_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:UsersliqiangAppDataLocalTemp
    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:UsersliqiangAppDataLocalTempcache_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:UsersliqiangAppDataLocalTempdynamic_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();
        }
    }
  • 相关阅读:
    Delphi中的钩子函数HOOK详解
    Delphi好书推荐
    Windows通知栏图标高级编程概述
    关于开机自动运行程序和自动启动服务
    如何在一个窗体中嵌入另一个窗体
    三层中如何在服务器与客户端之间传输自定义的'Record'类型数据的例子
    Delphi中的钩子函数HOOK详解
    STL(转)
    默认参数(c++)
    STL2
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/9613269.html
Copyright © 2011-2022 走看看