java緩存——(五)LocalCache本地緩存分享


LocalCache本地緩存分享

前言

一、本地緩存應用場景

二、java本地緩存標准

三、java開源緩存框架

四、LocalCache實現

結束語

 

前言

本次分享探討java平台的本地緩存,是指占用JVM的heap區域來緩沖存儲數據的緩存組件。

 

一、本地緩存應用場景


localcache有着極大的性能優勢:

1. 單機情況下適當使用localcache會使應用的性能得到很大的提升。

2. 集群環境下對於敏感性要求不高的數據可以使用localcache,只配置簡單的失效機制來保證數據的相對一致性。

哪些數據可以存儲到本地緩存?

1.訪問頻繁的數據;

2.靜態基礎數據(長時間內不變的數據);

3.相對靜態數據(短時間內不變的數據)。

 

二、java本地緩存標准

Java緩存新標准(javax.cache),這個標准由JSR107所提出,已經被包含在Java EE 7中。

特性:

1.原子操作,跟java.util.ConcurrentMap類似

2.從緩存中讀取

3.寫入緩存

4.緩存事件監聽器

5.數據統計

6.包含所有隔離(ioslation)級別的事務

7.緩存注解(annotations)

8.保存定義key和值類型的泛型緩存

9.引用保存(只適用於堆緩存)和值保存定義

                  

但目前應用不是很普遍。

 

三、java開源緩存框架

比較有名的本地緩存開源框架有:

1.EHCache

EHCache是一個純java的在進程中的緩存,它具有以下特性:快速,簡單,為Hibernate2.1充當可插入的緩存,最小的依賴性,全面的文檔和測試。

BUG: 過期失效的緩存元素無法被GC掉,時間越長緩存越多,內存占用越大,導致內存泄漏的概率越大。

 

2.OSCache

OSCache有以下特點:緩存任何對象,你可以不受限制的緩存部分jsp頁面或HTTP請求,任何java對象都可以緩存。擁有全面的API--OSCache API給你全面的程序來控制所有的OSCache特性。永久緩存--緩存能隨意的寫入硬盤,因此允許昂貴的創建(expensive-to-create)數據來保持緩存,甚至能讓應用重啟。支持集群--集群緩存數據能被單個的進行參數配置,不需要修改代碼。緩存記錄的過期--你可以有最大限度的控制緩存對象的過期,包括可插入式的刷新策略(如果默認性能不需要時)。

 

3.JCache

Java緩存新標准(javax.cache)

 

4.cache4j

cache4j是一個有簡單API與實現快速的Java對象緩存。它的特性包括:在內存中進行緩存,設計用於多線程環境,兩種實現:同步與阻塞,多種緩存清除策略:LFU, LRU, FIFO,可使用強引用。

 

5.ShiftOne

ShiftOne Java Object Cache是一個執行一系列嚴格的對象緩存策略的Java lib,就像一個輕量級的配置緩存工作狀態的框架。

 

6.WhirlyCache

Whirlycache是一個快速的、可配置的、存在於內存中的對象的緩存。

 

四、LocalCache實現

1、LocalCache簡介

LocalCache是一個精簡版本地緩存組件,有以下特點:

1.  有容量上限maxCapacity;

2.  緩存達到容量上限時基於LRU策略來移除緩存元素;

3.  緩存對象的生命周期(緩存失效時間)由調用方決定;

4.  緩存對象失效后,將會有定時清理線程來清理掉,不會導致內存泄漏。

5.  性能比Ehcache稍強。

 

2、總體設計

LocalCache總體設計:

1.  緩存元素 CacheElement;

2.  緩存容器 LRULinkedHashMap;

3.  緩存接口 Cache;

4.  緩存組件實現 LocalCache。

 

3、詳細設計

1.  CacheElement設計

/**
 * 緩存元素
 *
 */
public class CacheElement {
    private Object key;
    private Object value;
    private long createTime;
    private long lifeTime;
    private int hitCount;
 
    public CacheElement() {
    }
 
    public CacheElement(Object key ,Object value) {
        this.key = key;
        this.value = value;
        this.createTime = System.currentTimeMillis();
    }
    
    public Object getKey() {
        return key;
    }
 
    public void setKey(Object key) {
        this.key = key;
    }
 
    public Object getValue() {
        hitCount++;
        return value;
    }
 
    public void setValue(Object value) {
        this.value = value;
    }
 
    public long getCreateTime() {
        return createTime;
    }
 
    public void setCreateTime(long createTime) {
        this.createTime = createTime;
    }
 
    public int getHitCount() {
        return hitCount;
    }
 
    public void setHitCount(int hitCount) {
        this.hitCount = hitCount;
    }
 
    public long getLifeTime() {
        return lifeTime;
    }
 
    public void setLifeTime(long lifeTime) {
        this.lifeTime = lifeTime;
    }
    
    public boolean isExpired() {
        boolean isExpired = System.currentTimeMillis() - getCreateTime() > getLifeTime();
        return isExpired;
    }
 
    /*
     * (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("[ key=").append(key).append(", isExpired=").append(isExpired())
            .append(", lifeTime=").append(lifeTime).append(", createTime=").append(createTime)
            .append(", hitCount=").append(hitCount)
            .append(", value=").append(value).append(" ]");
        return sb.toString();
    }
    
    /*
     * (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    public final int hashCode(){
        if(null == key){
            return "".hashCode();
        }
        return this.key.hashCode();
    }
    
    /*
     * (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    public final boolean equals(Object object) {
        if ((object == null) || (!(object instanceof CacheElement))) {
            return false;
        }
 
        CacheElement element = (CacheElement) object;
        if ((this.key == null) || (element.getKey() == null)) {
            return false;
        }
 
        return this.key.equals(element.getKey());
    }
}

2.  LRULinkedHashMap實現

 

 
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 實現 LRU策略的 LinkedHashMap
 *
 * @param 
 * @param 
 */
public class LRULinkedHashMap extends LinkedHashMap  
{  
    protected static final long serialVersionUID = 2828675280716975892L;
    
    protected static final int DEFAULT_MAX_ENTRIES = 100;
    
    protected final int initialCapacity; 
    protected final int maxCapacity; 
    protected boolean enableRemoveEldestEntry = true;//是否允許自動移除比較舊的元素(添加元素時)
    
    protected static final float DEFAULT_LOAD_FACTOR = 0.8f;  
    protected final Lock lock = new ReentrantLock();  
 
    public LRULinkedHashMap(int initialCapacity)  
    {  
        this(initialCapacity, DEFAULT_MAX_ENTRIES);
    }
    
    public LRULinkedHashMap(int initialCapacity ,int maxCapacity)  
    {  
        //set accessOrder=true, LRU
        super(initialCapacity, DEFAULT_LOAD_FACTOR, true); 
        
        this.initialCapacity = initialCapacity; 
        this.maxCapacity = maxCapacity; 
    }
 
    /*
     *   (non-Javadoc)
     * @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
     */
    protected boolean removeEldestEntry(java.util.Map.Entry eldest)  
    {  
        return enableRemoveEldestEntry && ( size() > maxCapacity );
    }  
 
    /*
     *   (non-Javadoc)
     * @see java.util.LinkedHashMap#get(java.lang.Object)
     */
    public V get(Object key)  
    {  
        try {  
            lock.lock();  
            return super.get(key);  
        }  
        finally {  
            lock.unlock();  
        }  
    }  
 
    /*
     *   (non-Javadoc)
     * @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
     */
    public V put(K key, V value)  
    {  
        try {  
            lock.lock();  
            return super.put(key, value);  
        }  
        finally {  
            lock.unlock();  
        }  
    }  
    
    /*
     * (non-Javadoc)
     * @see java.util.HashMap#remove(java.lang.Object)
     */
    public V remove(Object key) {
        try {  
            lock.lock();
            return super.remove(key);
        }  
        finally {  
            lock.unlock();  
        }
    }
    
    /*
     * (non-Javadoc)
     * @see java.util.LinkedHashMap#clear()
     */
    public void clear() {
         try {  
             lock.lock();
             super.clear();
         }  
         finally {  
             lock.unlock();
         }
    }
    
    /*
     * (non-Javadoc)
     * @see java.util.HashMap#keySet()
     */
    public Set keySet() {
        try {  
            lock.lock();
            return super.keySet();
        }  
        finally {  
            lock.unlock();
        }
    }
    
    public boolean isEnableRemoveEldestEntry() {
        return enableRemoveEldestEntry;
    }
    public void setEnableRemoveEldestEntry(boolean enableRemoveEldestEntry) {
        this.enableRemoveEldestEntry = enableRemoveEldestEntry;
    }
    public int getInitialCapacity() {
        return initialCapacity;
    }
    public int getMaxCapacity() {
        return maxCapacity;
    }
}  

3.  Cache接口設計

 

/**
 * 緩存接口
 *
 */
public interface Cache {
    
    /**
     * 獲取緩存
     * @param key
     * @return
     */
    public  T getCache(Object key);
    
    /**
     * 緩存對象
     * @param key
     * @param value
     * @param milliSecond 緩存生命周期(毫秒)
     */
    public void putCache(Object key, Object value ,Long milliSecond);
    
    /**
     * 緩存容器中是否包含 key 
     * @param key
     * @return
     */
    public boolean containsKey(Object key);
    
    /**
     * 緩存列表大小
     * @return
     */
    public int getSize();
    
    /**
     * 是否啟用緩存
     */
    public boolean isEnabled();
    /**
     * 啟用 或 停止
     * @param enable
     */
    public void setEnabled(boolean enabled);
    
    /**
     * 移除所有緩存
     */
    public void invalidateCaches();
    
    /**
     * 移除 指定key緩存
     * @param key
     */
    public void invalidateCache(Object key);
}

4.  LocalCache實現

 

import java.util.Date;
import java.util.Iterator;
import java.util.Random;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * 本地緩存組件
 */
public class LocalCache implements Cache{
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    private LRULinkedHashMap

結束語

開源或有BUG,入手需謹慎。 

原文:https://blog.csdn.net/u011683530/article/details/51029734


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM