【Ehcache】ehcache2.5.2緩存的使用


  緩存的名字是ehcache。。。老是記得是encache....  

 

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

 

0.需要的jar包:

 

1.首先要了解緩存清除策略,官方文檔給出的有

  超過緩存指定的數量的時候按指定策略清除緩存的數據。參考:MemoryStoreEvictionPolicy類:

LRU - least recently used(最近最少使用)
LFU - least frequently used(最不經常使用)
FIFO - first in first out, the oldest element by creation time(清除最早緩存的數據,不關心是否經常使用)
CLOCK---FIFO - first in first out, the oldest element by creation time.(與FIFO一樣)

 

 

2.一個簡單的使用

1.使用緩存

配置文件:

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

 

 

各配置參數的含義:
  maxElementsInMemory:緩存中允許創建的最大對象數

  maxElementsOnDisk:磁盤中允許的最多對象數
  eternal:緩存中對象是否為永久的,如果是,超時設置將被忽略,對象從不過期。
  timeToIdleSeconds:緩存數據的鈍化時間,也就是在一個元素消亡之前,兩次訪問時間的最大時間間隔值,這只能在元素不是永久駐留時有效,如果該值是0 就意味着元素可以停頓無窮長的時間。
  timeToLiveSeconds:緩存數據的生存時間,也就是一個元素從構建到消亡的最大時間間隔值,這只能在元素不是永久駐留時有效,如果該值是0就意味着元素可以停頓無窮長的時間。
  overflowToDisk:內存不足時,是否啟用磁盤緩存。

  diskPersistent 是否持久化磁盤緩存,當這個屬性的值為true時,系統在初始化時會在磁盤中查找文件名為cache名稱,后綴名為data的文件。指重啟jvm后,數據是否有效。默認為false。

  memoryStoreEvictionPolicy:緩存滿了之后的淘汰算法。


  如果應用需要配置多個不同命名並采用不同參數的Cache,可以相應修改配置文件,增加需要的Cache配置即可。

 

兩個時間的詳細解釋:

  timeToLiveSeconds -->當對象自從被存放到緩存中后,如果處於緩存中的時間超過了 timeToLiveSeconds屬性值,這個對象就會過期,EHCache將把它從緩存中清除;即緩存自創建日期起能夠存活的最長時間,單位為秒(s)

  timeToIdleSeconds -->  當對象自從最近一次被訪問后,如果處於空閑狀態的時間超過了timeToIdleSeconds屬性值,這個對象就會過期,EHCache將把它從緩存中清空;即緩存被創建后,最后一次訪問時間到緩存失效之時,兩者之間的間隔,單位為秒(s)

  timeToLiveSeconds必須大於timeToIdleSeconds才有意義。

 

測試代碼:

package encache;

import java.util.Date;

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

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

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

    // 1.創建CacheManager
//    CacheManager cacheManager = CacheManager.create("E:/MavenEclipseWorkspace/encache/target/classes/ehcache.xml");// 也可以通過URL制定
    //一般用下面這種方式創建Cachemanager
//    CacheManager cacheManager = CacheManager.create();//默認讀取classpath目錄下面的ehcache.xml
     CacheManager cacheManager = new  CacheManager();//默認讀取classpath目錄下面的ehcache.xml

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

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

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

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

 

 

 結果:(注意存活時間是60s,注意標紅的信息)

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

 

並且在:C:\Users\liqiang\AppData\Local\Temp文件夾下面生成一個cache_test.data的文件。

 

 

刪除緩存只需要采用如下方法:

        // 4.刪除一個元素
        cache.remove("key");

 

 

 

2.獲取緩存配置

package encache;

import java.util.Date;

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

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

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

    // 1.創建CacheManager
    CacheManager cacheManager = new CacheManager();// 默認讀取classpath目錄下面的ehcache.xml

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

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

 

結果:

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

 

3.動態的修改緩存的配置:

代碼:

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

 

直接修改會報錯:

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

 

官方解釋:原因是上面encache.xml阻止了動態修改cache配置

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

 

 

解決辦法在官方解釋中說了,修改dynamicConfig屬性為true

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

 

 

修改之后再次執行下main代碼:

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

 

結果:(修改生效)

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

 

 

4.測試上面配置的一些作用:

修改上面的配置:

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

 

 

(1)測試緩存的生存時間:

package encache;

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

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

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

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

    public FirstCache() {

        // 1.創建CacheManager
        CacheManager cacheManager = new CacheManager();// 默認讀取classpath目錄下面的ehcache.xml

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

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

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

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

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

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

 

查看日志:

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

 

也就是6s之后緩存會自動清除。緩存時間生效。

 

(2)測試緩存對象數量問題:

package encache;

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

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

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

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

    public FirstCache() {

        // 1.創建CacheManager
        CacheManager cacheManager = new CacheManager();// 默認讀取classpath目錄下面的ehcache.xml

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

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

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

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

    }

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

 

結果:(只獲取到最后添加的兩個元素。FIFO策略也生效)

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

 

 

3.defaultCache的作用

  一直以為defaultCache的配置是會給我們創建一個cache,實際上是在程序中創建的cache會默認采用此配置。

 

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

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

 

 

也就是程序中顯示創建的Cache會默認使用defaultCache的配置。

 

package encache;

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

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

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

    public FirstCache() {

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

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

    }

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

 

結果:

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

 

4.encache原碼分析:

CacheManager

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

public class CacheManager {

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

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

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

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

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

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

  
    private static final long DELAY_UPDATE_CHECK = 1000;

   
    private static volatile CacheManager singleton;


    private static final MBeanRegistrationProviderFactory MBEAN_REGISTRATION_PROVIDER_FACTORY = new MBeanRegistrationProviderFactoryImpl();

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

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

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


    protected volatile Status status;

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

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

    
    protected final CacheManagerEventListenerRegistry cacheManagerEventListenerRegistry = new CacheManagerEventListenerRegistry();

    
    protected Thread shutdownHook;


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

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

 

Cache:

public class Cache implements InternalEhcache, StoreListener {


    public static final String DEFAULT_CACHE_NAME = "default";


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


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


    public static final long DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = CacheConfiguration.DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS;


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

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

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

 

Element:

  一個實現serializable和clonable的普通類,里面有key和value以及一些其他信息:

public class Element implements Serializable, Cloneable {

    private static final long serialVersionUID = 1098572221246444544L;

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

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

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

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


    @IgnoreSizeOf
    private final Object key;


    private final Object value;


    private volatile long version;


    private volatile long hitCount;


    private volatile int timeToLive = Integer.MIN_VALUE;

    private volatile int timeToIdle = Integer.MIN_VALUE;


    private transient volatile ElementEvictionData elementEvictionData;


    private volatile long lastUpdateTime;

    private volatile boolean cacheDefaultLifespan = true;

 

  Encache也可以進行集群等高級操作,待用到的時候查閱API即可。encache是新開一個線程進行緩存管理,JVM不停此線程也不會停止。

 

補充:在一個JVM如果創建兩個名字相同的cache,則會報錯,如下:

package encache;

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

import net.sf.ehcache.CacheManager;

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

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

 

結果:

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

 

補充:Element有一個構造方法可以指定緩存的時間等參數

package encache;

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

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

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

    public FirstCache() {

        // 1.創建CacheManager
        CacheManager cacheManager = new CacheManager();// 默認讀取classpath目錄下面的ehcache.xml

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

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

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

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

    }

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

 

結果:

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

 

補充:在學習了多線程之后對ehcache緩存進行的實驗多線程環境下

package encache;

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

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

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

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

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

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

    }
}

 

結果:

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

 

補充:自己封裝的一個工具類以及簡單的測試:

package ehcache;

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

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

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

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

    private static CacheManager cacheManager = CacheManager.create();
    // 靜態代碼塊創建緩存
    static {
        cacheManager.addCache(CACHE_NAME1);
        cacheManager.addCache(CACHE_NAME2);

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

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

    private EhcacheUtils() {

    }

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

    // 2.刪除元素
    // 2.1刪除單個元素
    /**
     * 刪除單個元素
     * 
     * @param cacheName
     *            緩存的名稱
     * @param key
     *            緩存的key
     * @return
     */
    public static boolean removeCacheByKey(String cacheName, String key) {
        try {
            Cache cache = cacheManager.getCache(cacheName);
            cache.remove(key);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

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

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

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

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

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

 ehcache.xml

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

 

測試代碼:

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

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

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

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

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

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

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

結果:(線程也沒有停止)

 

采用JVisualVM查看線程信息: (主線程結束了,但是仍然有ehcache創建的用戶線程,有3個用戶線程----創建CacheManager的時候會創建一個守護線程Statisxxxx,每次創建一個cache的時候也會創建一個用戶線程 cacheName.data)

 

源代碼跟蹤解釋線程:

(1)在  調用CacheManager cacheManager = CacheManager.create();   創建CacheManager的時候創建一個守護線程Statistics thread-_default_-1  統計線程

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

 

 

init中調用doInit(...)

 

doInit(...)創建線程(用到線程池進行周期性調用---此線程是一個守護線程)

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

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

 

 

(2)在調用cacheManager.addCache("cache1");的時候創建一個用戶線程:cache1.data (所以主線程結束,此線程也沒有結束,進程也沒有結束)

        ...這個代碼暫時沒有根出來,只是根到調用此方法后創建了一個用戶線程

 

最完美的就是再寫一個key生成器,KeyGenerator可以參考下面代碼:

package cn.xm.jwxt.utils;

import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM