【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();
}
}
【Ehcache】ehcache2.5.2缓存的使用的更多相关文章
- 项目搭建系列之三:SpringMVC框架下使用Ehcache对象、数据缓存
注明:该文章为以前写的文章,这里只更改了标题,无GitHub源码下载. 一.准备工作 如果已经成功搭建SpringMVC环境,那么就可以进入Ehcache的准备工作了.1.下载jar包 Ehca ...
- spring ehcache 页面、对象缓存
一.Ehcache基本用法 CacheManager cacheManager = CacheManager.create(); // 或者 cacheManager = CacheManager.g ...
- ehcache实现页面整体缓存和页面局部缓存
之前写过spring cache和ehcache的基本介绍和注解实现缓存管理,今天记录下web项目的页面缓存技术. 页面缓存是否有必要?. 这样说吧,几乎所有的网站的首页都是访问率最高的,而首页上的数 ...
- Spring+ehcache+redis两级缓存
问题描述 场景:我们的应用系统是分布式集群的,可横向扩展的.应用中某个接口操作满足以下一个或多个条件: 1. 接口运行复杂代价大, 2. 接口返回数据量大, 3. 接口的数据基本不会更改, 4. 接口 ...
- EhCache+Redis实现分布式缓存
Ehcache集群模式 由于 EhCache 是进程中的缓存系统,一旦将应用部署在集群环境中,每一个节点维护各自的缓存数据,当某个节点对缓存数据进行更新,这些更新的数据无法在其它节点中共享,这不仅会降 ...
- Springboot整合Ehcache 解决Mybatis二级缓存数据脏读 -详细
前面有写了一篇关于这个,但是这几天又改进了一点,就单独一篇在详细说明一下 配置 application.properties ,启用Ehcache # Ehcache缓存 spring.cache.t ...
- SpringBoot2 整合Ehcache组件,轻量级缓存管理
本文源码:GitHub·点这里 || GitEE·点这里 一.Ehcache缓存简介 1.基础简介 EhCache是一个纯Java的进程内缓存框架,具有快速.上手简单等特点,是Hibernate中默认 ...
- spring整合ehcache2.5.2缓存异常-- net.sf.ehcache.CacheException
报错如下: The source of the existing CacheManager is: DefaultConfigurationSource [ ehcache.xml or ehcach ...
- Ehcache(09)——缓存Web页面
http://haohaoxuexi.iteye.com/blog/2121782 页面缓存 目录 1 SimplePageCachingFilter 1.1 calculate ...
随机推荐
- BZOJ1001 BJOI2006狼抓兔子(最小割+最短路)
显然答案就是最小割.直接跑dinic也能过,不过显得不太靠谱. 考虑更正确的做法.作为一个平面图,如果要把他割成两半,那么显然可以用一条曲线覆盖且仅覆盖所有割边.于是我们把空白区域看成点,隔开他们的边 ...
- Navicat的使用技巧
1.快速查找表:选中一个数据库,然后在右侧会弹出如下的搜索框,搜索表名即可 2.快速清空表的内容:在窗口选中一张表,右键,选择“清空表”
- Leetcode 268.缺失数字 By Python
给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数. 示例 1: 输入: [3,0,1] 输出: 2 示例 2: 输入: [9,6,4,2 ...
- 自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表、Hosts_groups表、Interface表
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表.Hosts_grou ...
- 【BZOJ3202】项链(莫比乌斯反演,Burnside引理)
[BZOJ3202]项链(莫比乌斯反演,Burnside引理) 题面 BZOJ 洛谷 题解 首先读完题目,很明显的感觉就是,分成了两个部分计算. 首先计算本质不同的珠子个数,再计算本质不同的项链个数. ...
- C++ 容器:顺序性容器、关联式容器和容器适配器
什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象 ...
- js的append拼接html丢失css样式解决
htmlApp += "<li id='leftli"+lunci+"'>"; htmlApp += "<span id='left ...
- ReactNative组件之scrollView实现轮播
想要实现轮播效果,首先安装时间定时器 接下来就是在我们的项目中使用定时器 接下来我们将竖着的轮播图变成横着的 接下来我们调整间距 我们知道轮播图下方,还有5个圆点,那我们怎么做呢? 拿到每一个圆点 看 ...
- 【leetcode】 Merge Intervals
Merge Intervals Given a collection of intervals, merge all overlapping intervals. For example,Given ...
- 自己的Promise
废话不多说,直接上代码: class Promise2{ constructor(fn){ const _this=this; //重点 this.__queue=[]; this.__succ_re ...