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

简介: 在java项目开发中考虑到在使用HashMap在并发时会出现不正确行为,自己编写了采用static ConcurrentHashMap来完成静态缓存的处理,目的是为了能够用来处理高并发的线程安全类,如有问题请各指教: package com.

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

}
目录
相关文章
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
|
1月前
|
存储 Java API
深入剖析Java Map:不只是存储数据,更是设计艺术的体现!
【10月更文挑战第17天】在Java编程中,Map是一种重要的数据结构,用于存储键值对,并展现了设计艺术的精髓。本文深入剖析了Map的设计原理和使用技巧,包括基本概念、设计艺术(如哈希表与红黑树的空间时间权衡)、以及使用技巧(如选择合适的实现类、避免空指针异常等),帮助读者更好地理解和应用Map。
95 3
SpringMVC入门到实战------5、域对象共享数据 Request、Session、Application、Model、ModelAndView、Map、ModelMap的详细使用及代码实例
这篇文章详细解释了在IntelliJ IDEA中如何使用Mute Breakpoints功能来快速跳过程序中的后续断点,并展示了如何一键清空所有设置的断点。
SpringMVC入门到实战------5、域对象共享数据 Request、Session、Application、Model、ModelAndView、Map、ModelMap的详细使用及代码实例
|
23天前
|
存储 缓存 算法
分布式缓存有哪些常用的数据分片算法?
【10月更文挑战第25天】在实际应用中,需要根据具体的业务需求、数据特征以及系统的可扩展性要求等因素综合考虑,选择合适的数据分片算法,以实现分布式缓存的高效运行和数据的合理分布。
|
1月前
|
缓存 监控 前端开发
处理页面缓存中数据不一致的问题
【10月更文挑战第9天】
42 2
|
1月前
|
消息中间件 缓存 NoSQL
大数据-49 Redis 缓存问题中 穿透、雪崩、击穿、数据不一致、HotKey、BigKey
大数据-49 Redis 缓存问题中 穿透、雪崩、击穿、数据不一致、HotKey、BigKey
55 2
|
3月前
|
缓存 NoSQL Linux
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
131 1
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
域对象共享数据model、modelAndView、map、mapModel、request。从源码角度分析
这篇文章详细解释了在IntelliJ IDEA中如何使用Mute Breakpoints功能来快速跳过程序中的后续断点,并展示了如何一键清空所有设置的断点。
域对象共享数据model、modelAndView、map、mapModel、request。从源码角度分析
|
3月前
|
存储 算法 Java
Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据
Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据