採用static Map、ConcurrentHashMap實現數據緩存

在java項目開發中考慮到在使用HashMap在併發時會出現不正確行爲,自己編寫了採用static ConcurrentHashMap來完成靜態緩存的處理,目的是爲了能夠用來處理高併發的線程安全類,如有問題請各指教:

package com.hlwfarm.market.service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ctrip.market.commom.CLogger;
import com.ctrip.market.commom.DateTimeUtil;
import com.ctrip.market.commom.Distance;
import com.ctrip.market.commom.ServiceFactory;
import com.ctrip.market.entity.GfMsgscene;

public class MapCacheManager {

  private static CLogger<MapCacheManager> logger = new CLogger<MapCacheManager>();
  private volatile long updateTime = 0L;// 更新緩存時記錄的時間
  private volatile boolean updateFlag = true;// 正在更新時的閥門,爲false時表示當前沒有更新緩存,爲true時表示當前正在更新緩存
  private static Map<String, Object> cacheMap = new ConcurrentHashMap<String, Object>();// 緩存容器

  private static GfMsgsceneService gfMsgsceneService = (GfMsgsceneService) ServiceFactory
      .getInstance("gfMsgsceneService");// 場景信息

  public MapCacheManager() {
    this.LoadCache();// 加載緩存
    updateTime = System.currentTimeMillis();// 緩存更新時間
  }

  /**
   * 裝載緩存
   */
  private void LoadCache() {

    this.updateFlag = true;// 正在更新

    /********** 數據處理,將數據放入cacheMap緩存中 **begin ******/

    List<GfMsgscene> sceneList = gfMsgsceneService.queryByDateList();
    cacheMap.put("sceneList", sceneList);
    cacheMap.put("key2", "value2");

    logger.info("更新緩存完成", "更新緩存完成, date=" + DateTimeUtil.GetNowDateString());
    System.out.println("更新緩存完成:" + DateTimeUtil.GetNowDateString());

    /********** 數據處理,將數據放入cacheMap緩存中 ***end *******/
    this.updateFlag = false;// 更新已完成

  }

  /**
   * 返回緩存單個對象
   * 
   * @return
   */
  public Object getObjectCache(String key) {

    long currentTime = System.currentTimeMillis();
    synchronized (this) {

      // 如果當前緩存正在更新或者緩存超出時限,需重新加載
      if (this.IsTimeOut(currentTime)) {

        this.ReLoadCache();
        this.updateTime = currentTime;
      }
    }

    return this.cacheMap.get(key);
  }

  private boolean IsTimeOut(long currentTime) {
    logger.info("up", "up=" + (currentTime - this.updateTime));
    return ((currentTime - this.updateTime) >= 1000 * 60 * 10);// 超過時限,緩存1分鐘
  }

  /**
   * 獲取緩存項大小
   * 
   * @return
   */
  private int getCacheSize() {
    return cacheMap.size();
  }

  /**
   * 獲取更新時間
   * 
   * @return
   */
  private long getUpdateTime() {
    return this.updateTime;
  }

  /**
   * 獲取更新標誌
   * 
   * @return
   */
  private boolean getUpdateFlag() {
    return this.updateFlag;
  }

  /**
   * 重新裝載
   */
  private void ReLoadCache() {
    this.cacheMap.clear();
    this.LoadCache();
  }


  /**
    * @ClassName: CacheKeyEnum
    * @Description: 緩存數據key枚舉
    */
  public enum CacheKeyEnum {
    sceneList,
  }

}

  /**
   * 返回緩存全部
   * 
   * @return
   */
  public Map<String, Object> getMapCache() {

    long currentTime = System.currentTimeMillis();
    // 如果當前緩存正在更新或者緩存超出時限,需重新加載
    if (this.IsTimeOut(currentTime)) {
      synchronized (this) {
        this.ReLoadCache();
        this.updateTime = currentTime;
      }
    }

    return this.cacheMap;
  }

單元測試:

public class CacheTest {

 private static MapCacheManager cache = new MapCacheManager();

  @Test
  public void test() {
    for (int i = 0; i < 10; i++) {
      Map<String, Object> cacheMap = new ConcurrentHashMap<String, Object>();
      cacheMap = cache.getMapCache();
      Set<String> set = cacheMap.keySet();
      Iterator<String> it = set.iterator();

      while (it.hasNext()) {
        String key = it.next();
        System.out.println(key + "=" + JsonSerializer.serialize(cacheMap.get(key)));
      }
    }
  }

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