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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章