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();
        }
    }
  • 相关阅读:
    例题6-8 Tree Uva548
    例题6-7 Trees on the level ,Uva122
    caffe Mac 安装
    Codeforces Round #467 (Div. 1) B. Sleepy Game
    Educational Codeforces Round37 E
    Educational Codeforces Round 36 (Rated for Div. 2) E. Physical Education Lessons
    Good Bye 2017 E. New Year and Entity Enumeration
    Good Bye 2017 D. New Year and Arbitrary Arrangement
    Codeforces Round #454 D. Seating of Students
    浙大紫金港两日游
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/9613269.html
Copyright © 2011-2022 走看看