面试官:你是如何使用JDK来实现自己的缓存(支持高并发)?

数据库2025-11-05 14:09:486954

需求分析

项目中经常会遇到这种场景:一份数据需要在多处共享,面试有些数据还有时效性,官何高并过期自动失效。使用K实比如手机验证码,现自发送之后需要缓存起来,缓存然后处于安全性考虑,支持一般还要设置有效期,面试到期自动失效。官何高并我们怎么实现这样的使用K实功能呢?

解决方案

 使用现有的缓存技术框架,比如redis,现自ehcache。优点:成熟,缓存稳定,支持功能强大;缺点,面试项目需要引入对应的官何高并框架,不够轻量。云南idc服务商使用K实  如果不考虑分布式,只是在单线程或者多线程间作数据缓存,其实完全可以自己手写一个缓存工具。下面就来简单实现一个这样的工具。

先上代码: 

import java.util.HashMap;  import java.util.Map;  import java.util.concurrent.*;  /**   * @Author: lixk   * @Date: 2018/5/9 15:03   * @Description: 简单的内存缓存工具类   */  public class Cache {   //键值对集合   private final static Map<String, Entity> map = new HashMap<>();   //定时器线程池,用于清除过期缓存   private final static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();   /**   * 添加缓存   *   * @param key 键   * @param data 值   */   public synchronized static void put(String key, Object data) {   Cache.put(key, data, 0);   }   /**   * 添加缓存   *   * @param key 键   * @param data 值   * @param expire 过期时间,单位:毫秒, 0表示***长   */   public synchronized static void put(String key, Object data, long expire) {   //清除原键值对   Cache.remove(key);   //设置过期时间   if (expire > 0) {   Future future = executor.schedule(new Runnable() {   @Override   public void run() {   //过期后清除该键值对   synchronized (Cache.class) {   map.remove(key);   }   }   }, expire, TimeUnit.MILLISECONDS);   map.put(key, new Entity(data, future));   } else {   //不设置过期时间   map.put(key, new Entity(data, null));   }   }   /**   * 读取缓存   *   * @param key 键   * @return   */   public synchronized static Object get(String key) {   Entity entity = map.get(key);   return entity == null ? null : entity.getValue();   }   /**   * 读取缓存   *   * @param key 键   * * @param clazz 值类型   * @return   */   public synchronized static <T> T get(String key, Class<T> clazz) {   return clazz.cast(Cache.get(key));   }   /**   * 清除缓存   *   * @param key   * @return   */   public synchronized static Object remove(String key) {   //清除原缓存数据   Entity entity = map.remove(key);   if (entity == null) return null;   //清除原键值对定时器   Future future = entity.getFuture();   if (future != null) future.cancel(true);   return entity.getValue();   }   /**   * 查询当前缓存的键值对数量   *   * @return   */   public synchronized static int size() {   return map.size();   }   /**   * 缓存实体类   */   private static class Entity {   //键值对的value   private Object value;   //定时器Future    private Future future;   public Entity(Object value, Future future) {   this.value = value;   this.future = future;   }   /**   * 获取值   *   * @return   */   public Object getValue() {   return value;   }   /**   * 获取Future对象   *   * @return   */   public Future getFuture() {   return future;   }   }  } 

本工具类主要采用 HashMap+定时器线程池 实现,map 用于存储键值对数据,map的value是 Cache 的云服务器提供商内部类对象 Entity,Entity 包含 value 和该键值对的生命周期定时器 Future。Cache 类对外只提供了 put(key, value), put(key, value, expire), get(key), get(key, class), remove(key), size()几个同步方法。

当添加键值对数据的时候,首先会调用remove()方法,清除掉原来相同 key 的数据,并取消对应的定时清除任务,然后添加新数据到 map 中,并且,如果设置了有效时间,则添加对应的定时清除任务到定时器线程池。

测试 

import java.util.concurrent.ExecutionException;  import java.util.concurrent.ExecutorService;  import java.util.concurrent.Executors;  import java.util.concurrent.Future;  /**   * @Author: lixk   * @Date: 2018/5/9 16:40   * @Description: 缓存工具类测试   */  public class CacheTest {   /**   * 测试   *   * @param args   */   public static void main(String[] args) throws InterruptedException, ExecutionException {   String key = "id";   //不设置过期时间   System.out.println("服务器托管
本文地址:http://www.bzve.cn/html/28e65899313.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

全站热门

ubuntu系统如何切换root用户身份 本文将为大家介绍ubuntu切换root用户帐号方法,希望对大家有所帮助!说明:小编的这个建议只适合于10.10之前版本的ubuntu系统,后面的11.04,11.10。。。14.04系统因为采用的默认桌面不同,所以本经验不适用,若要使用,那么请安装GNOME桌面方法/步骤1、按照下面的方式打开终端工具,或者使用终端工具的快捷键Ctrl + Alt +T 打开终端2、终端工具打开后如下图所示,我们的操作就在这个窗口中进行3、切换root用户的的方式一执行命令 sudo su执行上面点命令后会要求我们输入当前我们的密码4、输入密码后就切换到root用户了,我们可以看到当前的用户已经是root了5、退出root用户的方法在切换成root用户后,我们只要执行exit命令就退出root用户账号了6、切换为root用户账户的第二种方法执行sudo -i命令也可以将当前用户有普通用户切换到root用户模式中7、执行命令后,一般也要求输入我们的密码,小编这里因为是刚切换到root用户不久,所以系统不要求输入密码,一般在10分钟之内我们来回切换root用户时系统不会提示输入密码,之后会要求我们再次输入密码END以上就是ubuntu切换root用户帐号方法介绍,希望对大家有一定的帮助!

Python字典:竟还有我不会的高阶玩法?

数据请求中Ajax、Fetch以及Axios的区别

金融业数据库自主创新之路

今天到网上搜ubuntu创建桌面快捷方式,发现尽是些不负责任,有问题的教程,故我也发教程一篇复制代码代码如下:具体内容参照下面的模板,顺便讲一下linux下软件的安装方法,以sublime text 2为例复制代码代码如下:复制代码代码如下:关于category,这里有一个主要列表可供选择he table below lists all Main Categories.Main Category Description NotesAudioVideo Application for presenting, creating, or processing multimedia (audio/video)Audio An audio application Desktop entry must include AudioVideo as wellVideo A video application Desktop entry must include AudioVideo as wellDevelopment An application for developmentEducation Educational softwareGame A gameGraphics Application for viewing, creating, or processing graphicsNetwork Network application such as a web browserOffice An office type applicationScience Scientific softwareSettings Settings applications Entries may appear in a separate menu or as part of a Control CenterSystem System application, System Tools such as say a log viewer or network monitorUtility Small utility application, Accessoriesreferences:http://standards.freedesktop.org/menu-spec/latest/apa.html#main-category-registryhttp://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html

彻底搞懂 Select / Poll / Epoll,就这篇了!

在Ubuntu上安装和配置MySQL保姆级教程

Vue 是如何用 Rollup 打包的?

友情链接

滇ICP备2023006006号-39