采用static Map、ConcurrentHashMap实现数据缓存

本文介绍了一种基于ConcurrentHashMap实现的静态缓存管理方案,用于解决Java项目开发中HashMap在高并发环境下可能出现的问题。该方案通过MapCacheManager类实现了缓存的加载、更新及获取等功能,并提供了单元测试示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在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)));
      }
    }
  }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值