高速緩存實現

各位大蝦,本人實現了一個高速緩存,實現方式中依賴java的concurrent包ConcurrendHashMap,貼出代碼希望各位能夠討論一下如下的addElement()方法不加鎖,會不會出現線程問題(依照本人的理解應該不會,由於本人才疏學淺,還望不吝賜教,另外該方法的實現是參考<>)。

public class Cache<K, V> {

private final ConcurrentHashMap<K, FutureTask<V>> cache =
new ConcurrentHashMap<K, FutureTask<V>>();

private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
// private final Lock writeLock = lock.writeLock();

public V addElement(final K key, final V value) {
FutureTask<V> f = cache.get(key);
while (true) {
if (null == f) {
Callable<V> eval = new Callable<V>() {

@Override
public V call() throws Exception {
//此處實現比較簡單,但是如果創建一個V的對象需要比較消耗性能的話,
//這種緩存實現就有明顯的優勢
return value;
}

};
FutureTask<V> future = new FutureTask<V>(eval);
f = cache.putIfAbsent(key, future);
if (null == f) {
f = future;
future.run();
}
}

try {
return f.get();
} catch (Exception e) {
e.printStackTrace();
}
}
}

public V getElement(K key) {
try {
readLock.lock();
return cache.get(key).get();
} catch (Exception e) {
e.printStackTrace();
} finally {
readLock.unlock();
}
return null;
}
}

在具體實現中getElement()方法使用了讀鎖從而支持併發讀,在addElement()方法中沒有加任何鎖依靠FutureTask和實現邏輯來實現線程安全。如上實現優勢: 當線程進入addElement方法後,首先判斷對應key的Futuretask是否已經存在,如果不存在表明是第一次添加,然後利用Callable和Futuretask來創建一個value對象(如果創建value對象的代價非常昂貴的話,更能體現該實現的優勢).假如在第一個線程正在創建value的過程中,addElement方法進入第二個線程,此時第二個線程會首先判斷key對應的Futuretask是否已經存在,如不存在則利用Callable和Futuretask來創建一個value對象。試想此時的最好實現就是第二個線程判斷對象是否存在或者是否正在創建,如果存在或正在創建那麼最好的辦法就是等待第一個線程創建完成後直接來分享勝利的果實即可,不需要再進行創建後再依靠concurrentHashMap的putIfAbsent方法來判斷是否需要加入Map中,這種實現最明顯的優勢就是節約了創建一個複雜對象的開銷,這一點也是該實現的精華所在.
以上是本人對這個方法的理解,還望各位多多拍磚。。。。。。。。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章