返回顶部
首页 > 资讯 > 精选 >如何使用JDK来实现自己的缓存
  • 241
分享到

如何使用JDK来实现自己的缓存

2023-06-16 21:06:03 241人浏览 泡泡鱼
摘要

这篇文章给大家介绍如何使用jdk来实现自己的缓存,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。需求分析项目中经常会遇到这种场景:一份数据需要在多处共享,有些数据还有时效性,过期自动失效。比如手机验证码,发送之后需要缓存

这篇文章给大家介绍如何使用jdk来实现自己的缓存,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

需求分析

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

解决方案

  1.  使用现有的缓存技术框架,比如redis,ehcache。优点:成熟,稳定,功能强大;缺点,项目需要引入对应的框架,不够轻量。

  2.  如果不考虑分布式,只是在单线程或者多线程间作数据缓存,其实完全可以自己手写一个缓存工具。下面就来简单实现一个这样的工具。

先上代码:

import java.util.HashMap;  import java.util.Map;  import java.util.concurrent.*;    public class Cache {   //键值对集合   private final static Map<String, Entity> map = new HashMap<>();   //定时器线程池,用于清除过期缓存   private final static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();      public synchronized static void put(String key, Object data) {   Cache.put(key, data, 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));   }   }      public synchronized static Object get(String key) {   Entity entity = map.get(key);   return entity == null ? null : entity.getValue();   }      public synchronized static <T> T get(String key, Class<T> clazz) {   return clazz.cast(Cache.get(key));   }      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();   }      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;   }      public Object getValue() {   return value;   }      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;    public class CacheTest {      public static void main(String[] args) throws InterruptedException, ExecutionException {   String key = "id";   //不设置过期时间   System.out.println("***********不设置过期时间**********");   Cache.put(key, 123);   System.out.println("key:" + key + ", value:" + Cache.get(key));   System.out.println("key:" + key + ", value:" + Cache.remove(key));   System.out.println("key:" + key + ", value:" + Cache.get(key));   //设置过期时间   System.out.println("  ***********设置过期时间**********");   Cache.put(key, "123456", 1000);   System.out.println("key:" + key + ", value:" + Cache.get(key));   Thread.sleep(2000);   System.out.println("key:" + key + ", value:" + Cache.get(key));      System.out.println("  ***********并发性能测试************");   //创建有10个线程的线程池,将1000000次操作分10次添加到线程池   ExecutorService executorService = Executors.newFixedThreadPool(10);   Future[] futures = new Future[10];      {   long start = System.currentTimeMillis();   for (int j = 0; j < 10; j++) {   futures[j] = executorService.submit(() -> {   for (int i = 0; i < 100000; i++) {   Cache.put(Thread.currentThread().getId() + key + i, i, 300000);   }   });   }   //等待全部线程执行完成,打印执行时间   for (Future future : futures) {   future.get();   }   System.out.printf("添加耗时:%dms  ", System.currentTimeMillis() - start);   }      {   long start = System.currentTimeMillis();   for (int j = 0; j < 10; j++) {   futures[j] = executorService.submit(() -> {   for (int i = 0; i < 100000; i++) {   Cache.get(Thread.currentThread().getId() + key + i);   }   });   }   //等待全部线程执行完成,打印执行时间   for (Future future : futures) {   future.get();   }   System.out.printf("查询耗时:%dms  ", System.currentTimeMillis() - start);   }   System.out.println("当前缓存容量:" + Cache.size());   }  }

测试结果:

***********不设置过期时间**********  key:id, value:123  key:id, value:123  key:id, value:null  ***********设置过期时间**********  key:id, value:123456  key:id, value:null  ***********并发性能测试************  添加耗时:2313ms  查询耗时:335ms  当前缓存容量:1000000

测试程序使用有10个线程的线程池来模拟并发,总共执行一百万次添加和查询操作,时间大约都在两秒多,表现还不错,每秒40万读写并发应该还是可以满足大多数高并发场景的^_^

关于如何使用JDK来实现自己的缓存就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: 如何使用JDK来实现自己的缓存

本文链接: https://lsjlt.com/news/285226.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何使用JDK来实现自己的缓存
    这篇文章给大家介绍如何使用JDK来实现自己的缓存,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。需求分析项目中经常会遇到这种场景:一份数据需要在多处共享,有些数据还有时效性,过期自动失效。比如手机验证码,发送之后需要缓存...
    99+
    2023-06-16
  • Java缓存使用如何实现的
    这篇文章将为大家详细讲解有关Java缓存使用如何实现的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Java缓存主要有LRU和FIFO,LRU是Least Recently Used的缩写,...
    99+
    2023-05-31
    缓存 java ava
  • 如何使用PHP缓存函数实现实时数据缓存?
    PHP缓存函数是一种将数据存储在内存或磁盘上的技术。该技术可以大大提高应用程序的性能和响应速度,尤其在需要频繁查询数据库的情况下。本文将介绍如何使用PHP缓存函数实现实时数据缓存。 一、什么是缓存? 缓存是将数据存储在内存或磁盘上,以便快速...
    99+
    2023-08-11
    缓存 函数 实时
  • C#使用CefSharp自定义缓存实现
    本文介绍CefSharp的缓存实现,先来说说添加缓存的好处: 提高页面加载加速:CefSharp缓存可以缓存已经加载过的页面和资源,当用户再次访问相同的页面时,可以直接从缓存中加载,...
    99+
    2023-05-18
    CefSharp自定义缓存 CefSharp基本配置 缓存 cefsharp教程
  • 使用MyBatis如何实现一级缓存与二级缓存
    这期内容当中小编将会给大家带来有关使用MyBatis如何实现一级缓存与二级缓存,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。MyBatis缓存我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB...
    99+
    2023-05-31
    mybatis 一级缓存 二级缓存
  • 如何使用 Python 实现同步缓存存储?
    在现代软件开发中,缓存是一个非常重要的概念。它可以显著提高应用程序的性能,因为它允许我们将一些经常使用的数据存储在内存中,从而减少对磁盘或数据库等存储介质的访问。但是,缓存的使用也会带来一些问题,其中最重要的问题之一是数据一致性。 在这篇文...
    99+
    2023-10-18
    存储 同步 缓存
  • 使用mybatis如何实现查询缓存
    这篇文章将为大家详细讲解有关使用mybatis如何实现查询缓存,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1 缓存的意义将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上...
    99+
    2023-05-31
    mybatis 查询缓存
  • 用node如何实现缓存
    本文小编为大家详细介绍“用node如何实现缓存”,内容详细,步骤清晰,细节处理妥当,希望这篇“用node如何实现缓存”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。缓存原理浏览器缓存的基本原理是将静态资源(如 CS...
    99+
    2023-07-05
  • Python如何手动编写一个自己的LRU缓存装饰器的方法实现
    LRU缓存算法,指的是近期最少使用算法,大体逻辑就是淘汰最长时间没有用的那个缓存,这里我们使用有序字典,来实现自己的LRU缓存算法,并将其包装成一个装饰器。 1、首先创建一个my_c...
    99+
    2024-04-02
  • 如何使用Java存储来提高Bash缓存的性能?
    Bash是一种流行的Unix shell,用于在Unix和Linux系统上执行命令。在Bash中,缓存被广泛使用来提高命令执行的速度。然而,在一些情况下,Bash的缓存性能可能会遇到瓶颈。本文将介绍如何使用Java存储来提高Bash缓存的性...
    99+
    2023-10-18
    存储 bash 缓存
  • 如何使用redis实现分布式缓存
    本文小编为大家详细介绍“如何使用redis实现分布式缓存”,内容详细,步骤清晰,细节处理妥当,希望这篇“如何使用redis实现分布式缓存”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识...
    99+
    2024-04-02
  • 在springboot使用spring 如何实现缓存cache
    本篇文章为大家展示了在springboot使用spring 如何实现缓存cache,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。声明式缓存Spring 定义 CacheManager 和 Cache...
    99+
    2023-05-31
    springboot spring cache
  • 如何使用MongoDB来实现web.py的session存储
    这篇文章将为大家详细讲解有关如何使用MongoDB来实现web.py的session存储,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。  web.py是一个python的...
    99+
    2024-04-02
  • 如何使用 ASP 缓存 实时 索引来优化网站?
    ASP缓存是一种基于内存的缓存机制,能够有效地提高网站的性能和响应速度。ASP缓存提供了一个轻量级的机制,可以存储一些经常使用的数据,以便在需要的时候快速访问。同时,ASP缓存也提供了一些强大的功能,比如实时索引,可以帮助我们更加高效地管理...
    99+
    2023-07-03
    缓存 实时 索引
  • 如何使用Java实现实时重定向缓存?
    在现代的应用程序中,缓存是一个非常重要的组件。它可以提高应用程序的性能,并减少对后端资源的访问。但是,在某些情况下,我们需要实时更新缓存,以确保缓存数据的准确性。在这种情况下,实时重定向缓存是一个非常有用的技术。 实时重定向缓存指的是一个...
    99+
    2023-06-22
    重定向 实时 缓存
  • cdn缓存如何实现
    实现原理:1.作为ICP,需要把域名解释权交给CDN运营商。2.作为CDN运营商,需要为ICP的域名提供公开的解析,为了实现sortlist,一般是把ICP的域名解释结果指向一个CNAME记录。3.需要进行sortlist时,CDN运营商利...
    99+
    2024-04-02
  • golang缓存如何实现
    这篇文章主要讲解了“golang缓存如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang缓存如何实现”吧!一、什么是缓存?缓存是一种提高数据读写性能的技术,类比于日常生活中的翻...
    99+
    2023-07-06
  • nodejs如何使用redis作为缓存介质实现封装缓存类
    小编给大家分享一下nodejs如何使用redis作为缓存介质实现封装缓存类,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!具体如下...
    99+
    2024-04-02
  • 如何使用批处理bat实现显示自己的IP
    这篇文章主要为大家展示了“如何使用批处理bat实现显示自己的IP”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用批处理bat实现显示自己的IP”这篇文章吧。显示自己的IP.bat代码如下:...
    99+
    2023-06-09
  • 使用Mybatis如何实现配置二级缓存
    这篇文章给大家介绍使用Mybatis如何实现配置二级缓存,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Mybatis的二级缓存配置相当容易,要开启二级缓存,只需要在你的Mapper 映射文件中添加一行:<...
    99+
    2023-05-31
    mybatis 二级缓存
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作