一道蚂蚁金服简单的上机笔试题

1.题目

说明:
构建一个本地缓存,缓存的对象是用户ID以及部分用户的信息。
当从缓存中获取某个用户数据时,如果发现该用户数据上次更新时间超过30分钟,则需要更新一次该缓存。
 
1.需考虑多线程访问的情况。
2.请不要使用第三方类库实现。
3.可以添加适当日志。
4.可以有适当的伪代码。
 
补充:UserInfo结构
public class UserInfo {
    private String userId;
    private String userName;
    private String cardNo;
    //省略其它信息和getter 和setter
}
 
完成下面的代码
 
//: TODO 可自行定义需要的变量
 
/**
 * 初始化用户信息缓存
 */
public void initUserInfoCache() {
    //: TODO 完成此处的代码
}
 
/**
 * 根据id从缓存中获取用户信息
 */ 
public UserInfo getUserInfoFromCacheById(String id) {
     //: TODO 完成此处的代码
}
 
/**
 * 根据id更新缓存用户信息
 */ 
public void updateUserInfoCache(String id) {
     //: TODO 完成此处的代码
}

2.答案

//用户信息缓存
private static Map<String,UserInfo> userCacheMap;
//更新时间缓存
private static Map<String,Long> lastUpdateTimeMap;
//过期时间30分钟
private static final long CACHE_TIME= 30*60*1000L;
 
/**
 * 初始化用户信息缓存
 */
public void initUserInfoCache() {

  if(lastUpdateTimeMap==null||userCacheMap==null){
     synchronized(UserInfo.class){
       if(lastUpdateTimeMap!=null&&userCacheMap!=null){
          return;
       }
       //add log
       System.out.println("initUserInfoCache start");

       Map<String,UserInfo> userCacheMapTemp = new ConcurrentHashMap<>();
       Map<String,Long> lastUpdateTimeMapTemp= new ConcurrentHashMap<>();
       while(true){
         //伪代码开始
         List<UserInfo> userInfoList = query some userInfos from db or others; //分页查询
         //伪代码结束
         if(userInfoList==null||userInfoList.size()==0){
            break;
         }
         //add log
         System.out.println("batch query userInfoList to cache,size is :"+userInfoList.size());

         for(UserInfo userInfo : userInfoList ){
           userCacheMapTemp.put(userInfo.getuserId(),userInfo);
           lastUpdateTimeMapTemp.put(userInfo.getuserId(),System.currentTimeMillis);
         }
       }
       //add log
       System.out.println("initUserInfoCache end");

       userCacheMap = userCacheMapTemp;
       lastUpdateTimeMap = lastUpdateTimeMapTemp;
     }     
  }
}

/**
 * 根据id从缓存中获取用户信息
 */ 
public UserInfo getUserInfoFromCacheById(String id) {
    if(id==null||"".equals(id)){
      //add log
      System.out.println("user id is empty!");

      return null;
    }
    //初始化缓存
    initUserInfoCache();

    Long lastUpdateTime = lastUpdateTimeMap.get(id);
    UserInfo userInfo = userCacheMap.get(id);
    if((System.currentTimeMillis-lastUpdateTime)>CACHE_TIME){
       synchronized(UserInfo.class){
         //超时30分钟,需更新缓存
         lastUpdateTime = lastUpdateTimeMap.get(id);
         if((System.currentTimeMillis-lastUpdateTime)>CACHE_TIME){
           updateUserInfoCache(id);
         }
       }
       userInfo = userCacheMap.get(id);
    }
    returun userInfo;
}

/**
 * 根据id更新缓存用户信息
 */ 
public void updateUserInfoCache(String id) {
   //add log
   System.out.println("updateUserInfoCache start,user id:"+id);

   //伪代码开始
   UserInfo newUserInfo = query latest userInfo from db or others by user id;
   //伪代码结束
   userCacheMap.put(newUserInfo.getId(),newUserInfo);
   lastUpdateTimeMap.put(newUserInfo.getId(),System.currentTimeMillis);

   //add log
   System.out.println("updateUserInfoCache end");
}