ehcache 在使用的时候,其实自己的实现已经很好了,它的内部实现有两种实现的方式:一种是内存的缓存方式,只存在内存,用完就删除了,只会和内存有关系:主要分为按
对应的elements的多少来存储,或者是指定内存大小来存储;第二种内存是存磁盘,就是写到硬盘上去,这种的好处就是不管你内存多大,都可以不用管,把内容写到磁盘上去,那么问题就来,我想先在内存存数据,然后内存不够的时候我想让写磁盘,那么这种需求该如何去实现呐 ?
可以肯定的是:现在ehcache本身是实现不了的,我早就已经测试过了,那么如何才能达到这种要求呐 ?
具体做法如下:
1.在cache 的管理层cachemanager中去管理cache 。
2.在定义自己的cache,实现 CacheEventListener 针对内部的notifyElementEvicted ,将cache移除的数据写入到磁盘上去。
3.让自己的cache被cachemanager去管理就好。
源码下载地址:http://download.csdn.net/detail/supingemail/8734915
具体代码如下:
MCache:
public class MCache implements CacheEventListener {
private String cacheName;
private Cache cache;
private String filePath;
public Map<String, File> selfCache = new HashMap<String, File>();
public MCache(String cacheName, Cache cache, CacheManager cacheManager) {
this.cacheName = cacheName;
this.cache = cache;
cache.getCacheEventNotificationService().registerListener(this);
filePath = cacheManager.getConfiguration().getDiskStoreConfiguration().getPath();
}
public Object get(String key) {
try {
if (cache.get(key) != null) {
return cache.get(key);
} else {
if (selfCache.get(key) != null) {
File file = selfCache.get(key);
InputStream is = new FileInputStream(file);
DataInputStream dis = new DataInputStream(is);
//class
String className = dis.readUTF();
WriteableObject wObject = (WriteableObject) Class.forName(className).newInstance();
wObject.read(is);
put(key, wObject);
return wObject;
} else {
return null;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public boolean put(String key, Object value) {
try {
cache.put(new Element(key, value));
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
@Override
public void notifyElementRemoved(Ehcache cache, Element element)
throws CacheException {
}
@Override
public void notifyElementPut(Ehcache cache, Element element)
throws CacheException {
}
@Override
public void notifyElementUpdated(Ehcache cache, Element element)
throws CacheException {
}
@Override
public void notifyElementExpired(Ehcache cache, Element element) {
}
@Override
public void notifyElementEvicted(Ehcache cache, Element element) {
WriteableObject wObject = (WriteableObject) element.getObjectValue();
String key = (String) element.getObjectKey();
File file = new File(filePath + key + ".dat");
selfCache.put((String) element.getObjectKey(), file);
try {
OutputStream outputStream = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(outputStream);
try {
dos.writeUTF(wObject.getClass().getName());
wObject.write(outputStream);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
@Override
public void notifyRemoveAll(Ehcache cache) {
}
@Override
public void dispose() {
}
public Object clone() {
return this;
}
public String getCacheName() {
return cacheName;
}
public void setCacheName(String cacheName) {
this.cacheName = cacheName;
}
public Cache getCache() {
return cache;
}
public void setCache(Cache cache) {
this.cache = cache;
}
}
MCacheManager :
public class MCacheManager {
private static Logger logger = LoggerFactory.getLogger(MCacheManager.class.getName());
private Map<Object, MCache> cacheMap = new HashMap<Object, MCache>();
private static String CACHE_PATH = "java.io.tmpdir";
private static String MAX_MEMORY = "512m";
private static final String BLOCK_MAX_MEMORY = "512m";
private static MCacheManager instance = null;
private Properties props = null;
private CacheManager cacheManager = null;
private Cache memoryCache = null;
private MCache dataCache = null;
private static final String removePolicy = "LFU";
public static MCacheManager getInstance() {
if (instance == null) {
synchronized (MCacheManager.class) {
if (instance == null) {
instance = new MCacheManager();
}
}
}
return instance;
}
private MCacheManager() {
super();
double maxMemory = (Runtime.getRuntime().maxMemory() * 0.4) / (1024 * 1024);// m
MAX_MEMORY = maxMemory + "";
}
public Cache memoryCache() {
if (memoryCache == null) {
synchronized (this) {
if (memoryCache == null) {
String maxMemory = getProperty("block.cache.max.memory",BLOCK_MAX_MEMORY);
memoryCache = getCache("__memoryCache__", maxMemory, false);
}
}
}
return memoryCache;
}
public MCache dataCache(String cacheName ,Cache cache , CacheManager cacheManager) {
if (dataCache == null) {
synchronized (this) {
if (dataCache == null) {
dataCache = new MCache(cacheName, cache, cacheManager);
}
}
}
return dataCache;
}
public Cache getCache(String cacheName, String maxMemory ) {
Cache cache = getCacheManager().getCache(cacheName);
if (cache == null) {
synchronized (this) {
cache = getCacheManager().getCache(cacheName);
if (cache == null) {
CacheConfiguration cacheConfig = new CacheConfiguration();
cacheConfig.name(cacheName);
cacheConfig.eternal(false);
String removeTag = getProperty("cache.remove.tag", removePolicy);
cacheConfig.setMemoryStoreEvictionPolicy(removeTag);
cacheConfig.setOverflowToDisk(false);
cacheConfig.setDiskPersistent(false);
cacheConfig.setMaxBytesLocalHeap(maxMemory);
cache = new Cache(cacheConfig);
getCacheManager().addCache(cache);
}
}
}
return cache;
}
private Cache getCache(String cacheName, String maxMemory, boolean saveDisk) {
Cache cache = getCacheManager().getCache(cacheName);
if (cache == null) {
synchronized (this) {
cache = getCacheManager().getCache(cacheName);
if (cache == null) {
CacheConfiguration cacheConfig = new CacheConfiguration();
cacheConfig.name(cacheName);
cacheConfig.eternal(false);
String removeTag = getProperty("cache.remove.tag", removePolicy);
cacheConfig.setMemoryStoreEvictionPolicy(removeTag);
cacheConfig.setOverflowToDisk(saveDisk);
cacheConfig.setDiskPersistent(false);
cacheConfig.setMaxBytesLocalHeap(maxMemory);
cache = new Cache(cacheConfig);
getCacheManager().addCache(cache);
}
}
}
return cache;
}
public CacheManager getCacheManager() {
if (cacheManager == null) {
synchronized (this) {
if (cacheManager == null) {
Configuration configuration = new Configuration();
DiskStoreConfiguration dscg = new DiskStoreConfiguration();
String cacheFilePath = getProperty("cache.path.disk", CACHE_PATH);
File file = new File(cacheFilePath);
if (!file.exists()) {
file.mkdirs();
}
CACHE_PATH = cacheFilePath;
dscg.setPath(cacheFilePath);
configuration.diskStore(dscg);
configuration.setMaxBytesLocalHeap(getProperty("cache.manager.max.memory", MAX_MEMORY));
configuration.setDynamicConfig(true);
configuration.setMonitoring("autodetect");
configuration.setUpdateCheck(false);
cacheManager = new CacheManager(configuration);
}
}
}
return cacheManager;
}
public void addCache(MCache mCache){
cacheMap.put(mCache.getCacheName(), mCache);
}
public MCache get(String cacheName){
if (cacheMap.containsKey(cacheName)) {
return (MCache) cacheMap.get(cacheName);
}else {
return null;
}
}
private String getProperty(String key, String defaultValue) {
if (props == null) {
synchronized (this) {
if (props == null) {
try {
InputStream stream = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("/cache.properties");
if (stream == null) {
stream = MCacheManager.class
.getResourceAsStream("/cache.properties");
}
props = new Properties();
props.load(stream);
} catch (Exception e) {
logger.error(e.getMessage());
}
}
}
}
return props.getProperty(key, defaultValue);
}
private boolean deleteCache(){
File file = new File(CACHE_PATH);
File[] folderFiles = file.listFiles();
for (File f : folderFiles) {
f.delete();
}
return true;
}
}
写磁盘 WriteableObject 接口
public interface WriteableObject extends Serializable {
public void read(InputStream inputStream) throws IOException;
public boolean write(OutputStream outputStream) throws IOException;
}
实例类PersonBean :
public class PersonBean implements WriteableObject{
private static final long serialVersionUID = 1L;
private String name;
private List<String> list;
public PersonBean(){
super();
}
public PersonBean(String name, List<String> list) {
this.name = name;
this.list = list;
}
@Override
public void read(InputStream inputStream) throws IOException {
DataInputStream dis = new DataInputStream(inputStream);
name = dis.readUTF();
int size = dis.readInt();
list = new ArrayList<>();
for (int i = 0; i < size; i++) {
list.add(dis.readLine());
}
}
@Override
public boolean write(OutputStream outputStream) throws IOException {
DataOutputStream dos = new DataOutputStream(outputStream);
dos.writeUTF(name);
dos.writeInt(list.size());
for (String obj : list) {
dos.writeBytes(obj);
}
dos.close();
return true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
cache测试类Test :
public class Test {
static int index = 0;
public static void main(String[] args) throws IOException {
CacheManager cacheManager = MCacheManager.getInstance().getCacheManager();
Cache cache = MCacheManager.getInstance().memoryCache();
long maxMemory = cache.getCacheConfiguration().getMaxBytesLocalHeap();
System.out.println(" maxMemory = " + maxMemory / (1024 * 1024) + "mb");
MCache mCache = new MCache("testCache", cache,cacheManager);
MCacheManager.getInstance().addCache(mCache);
while (true) {
mCache.put("myCache" + index, beanInstance());
if (index > 100) {
String result = "----------------------" + index
+ "----------------------," + " \ncache.getSize() : "
+ cache.getSize() + ",\ncache.getDiskStoreSize() : "
+ cache.getDiskStoreSize() + ","
+ " \ncache.getMemoryStoreSize() : "
+ cache.getMemoryStoreSize() + ","
+ " \ncache.calculateInMemorySize() : "
+ cache.calculateInMemorySize()
+ ", \ncache.getKeys() : " + cache.getKeys()
+ ",\n keys size :" + cache.getKeys().size();
// buffer.append(result);
System.out.println(result);
break;
}
index++;
}
//List<String> keyList = mCache.
}
/**
* 放入数据到集合.
*
* @return
*/
private static PersonBean beanInstance() {
List<String> list = new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
list.add("JavaCache-EHCache系列之计算实例占用的内存大小(SizeOf引擎),基本数据的类型的大小是固定的,这里就不多说了。对于非基本类型的Java对象,其大小就值得商榷。加入的key是:"
+ i);
}
return new PersonBean("PersonBean"+index,list);
}
}
就这样,就完成了:先写内存,再写入磁盘的操作。。。