java基本类实现二级缓存

LRU linkedhashmap中由于重写 removeEldestEntry后只能一个一个的删除,如果删除后的内容需要持久化的话将会影响效率,因此需要批量转储,如果能访问hashmap的header after等私有变量就好了,可是未遂

本人解决方案如下:
首先将要删除的linkedhashmap中的removeEldestEntry(java.util.Map.Entry<K, V> eldest)真正删除,然后将最终元素记录到缓冲map中,作为一个cache,然后在批量转储

 

import java.util.LinkedHashMap;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
*
* @param <K>
* @param <V>
* 定长 LRU hashmap 当长度超过maxCapacity自动删除最不常访问的元素
*/
public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
private final int maxCapacity;
private static LinkedHashMap batchToDelete = new LinkedHashMap();
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private final Lock lock = new ReentrantLock();

public LRULinkedHashMap(int maxCapacity) { // false是插入顺序
super(maxCapacity, DEFAULT_LOAD_FACTOR, false);
this.maxCapacity = maxCapacity;
}

@Override
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
boolean needRemove = false;
// 转储待写代码 eldest将要被删除的元素 还需要维护 accidsessions的删除操作
if (size() >= maxCapacity * Constants.RANGETODELETE) {
batchToDelete.put(eldest.getKey(), eldest.getValue());
needRemove = true;
}
System.err.println(batchToDelete.size());
if (batchToDelete.size() > maxCapacity * Constants.TODELETECACHE) {
this.cleanEntitiesInLRU();
}
return needRemove;
}

private void cleanEntitiesInLRU() {
try {
Set<K> keyset = batchToDelete.keySet();
// 批量转储息道此处,可通过另起线程监听由另外线程完成
System.err.println(batchToDelete.size() + " 待删区个数");
// for (K k : keyset) {
// this.remove(k);
// }
batchToDelete.clear();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}

@Override
public V get(Object key) {
return super.get(key);
// try {
// lock.lock();
// }
// finally {
// lock.unlock();
// }
}

@Override
public V put(K key, V value) {
try {
lock.lock();
return super.put(key, value);
} finally {
lock.unlock();
}
}
}

junit测试用例:

import static org.junit.Assert.*;

import org.junit.Test;

import LRULinkedHashMap;

public class TestLruHashMap {

@Test
public void testLRULinkedHashMap() {
LRULinkedHashMap<String, String> testSession=new LRULinkedHashMap<String, String>(100);
for(int i=0;i<1000;i++){
try{
Object obj = (i%3==0)?testSession.put("session "+i/3, i+" lru"):testSession.put("session "+i, i+" lru");
System.out.println(testSession.size()+" " +testSession);
}catch(Exception e){
e.printStackTrace();
}
}
}


}
LinkedBlockingQueue 可以做为队列方式的缓存实现 优势:引入了两个锁,一个入队列锁,一个出队列锁。当然同时有一个队列不满的Condition和一个队列不空的Condition。其实参照锁机制前面介绍过的生产者-消费者模型就知道,入队列就代表生产者,出队列就代表消费者。为什么需要两个锁?一个锁行不行?其实一个锁完全可以,但是一个锁意味着入队列和出队列同时只能有一个在进行,另一个必须等待其释放锁。而从ConcurrentLinkedQueue的实现原理来看,事实上head和last (ConcurrentLinkedQueue中是tail)是分离的,互相独立的,这意味着入队列实际上是不会修改出队列的数据的,同时出队列也不会修改入队列,也就是说这两个操作是互不干扰的。更通俗的将,这个锁相当于两个写入锁,入队列是一种写操作,操作head,出队列是一种写操作,操作tail。可见它们是无关的。但是并非完全无关,后面详细分析

http://www.blogjava.net/xylz/archive/2011/02/15/326988.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值