Java 8实现缓存服务(维护两种淘汰策略(FIFO LRU)的并发高速缓存)

计算机考研考博经典考题汇总(一次刷新世界观-我相信VIP总是有原因的) 操作系统 操作系统的特点? – 共享:资源可被多个并发执行的进程使用 – 并发:可以在同一时间间隔处理多个进程,需要硬件支持 – 虚拟:将物理实体映射成为多个虚拟设备 – 异步:进程执行走走停停,每次进程执行速度可能不同,但OS需保证进程每次执行结果相同 进程的三个组成部分? 程序段、数据段、PCB(Process Control Block) 并发与并行区别? 并发:同一间隔 并行:同一时刻 进程切换的过程? 保持处理机上下文 -> 更新PCB -> 把PCB移入相应队列(就绪、阻塞) -&g 阅读详情

场景:请使用Java 8实现缓存服务。
该服务可以提供中等级别的缓存同时访问。


要实施的访问操作包括:
           1. get(key) - 此操作将获取列表中键的值。如果密钥不存在,则返回-1。
           2. set(key,value) - 如果密钥不存在,此操作将在列表中插入新的键/值,否则不执行任何操作。
           3.缓存的大小可通过属性文件进行配置


要求:1.实现具有最近最少使用(LRU)策略的通用基于内存的缓存作为列表
           2.实现访问操作的并发性。


主要代码实现:

package dpnice.cache;

import dpnice.common.GlobalConstants;
import dpnice.util.ConfigurationUtils;
import org.apache.log4j.Logger;

import java.util.concurrent.*;


/**
 * 维护两种淘汰策略(FIFO LRU)的高速缓存
 *
 * @author DPn!ce   date 2018 07 12 上午 10:19
 */
public class FastCache<K, V> {
    private final static Logger log = Logger.getLogger(FastCache.class);
    /**
     * 最大缓存大小
     * 单位 byte
     */
    private Long cacheSize;
    /**
     * 初始化内存大小
     */
    private Long initCacheSize;
    /**
     * FIFO并发缓存容器
     */
    private ConcurrentHashMap<Object, CacheNode> nodesFIFO;
    /**
     * FIFO并发缓存容器大小
     */
    private int nodesFIFOCacheSize = 10000;
    /**
     * FIFO链表头
     */
    private CacheNode firstFIFO;
    /**
     * FIFO链表尾
     */
    private CacheNode lastFIFO;
    /**
     * LRU并发缓存容器
     */
    private ConcurrentHashMap<Object, CacheNode> nodesLRU;
    /**
     * LRU链表头
     */
    private CacheNode firstLRU;
    /**
     * LRU链表尾
     */
    private CacheNode lastLRU;


    public FastCache() {
        setCacheSize();
        initCacheSize = getCurrentSize();
        nodesLRU = new ConcurrentHashMap<>();
        nodesFIFO = new ConcurrentHashMap<>(nodesFIFOCacheSize);
    }

    /**
     * 添加缓存
     *
     * @param key   键
     * @param value 对应值
     */
    public synchronized void put(K key, V value) {
        CacheNode cacheNode = null;
        try {
            cacheNode = getCacheNode(key);
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
        if (cacheNode == null) {
            //FIFO缓存容器是否已经超过大小
            if (nodesFIFO.size() > nodesFIFOCacheSize) {
                if (firstFIFO != null) {
                    //先进先出
                    nodesFIFO.remove(firstFIFO.getKey());
                    firstFIFO.getNext().setFront(null);
                    firstFIFO = firstFIFO.getNext();
                }
            }
            cacheNode = new CacheNode();
            cacheNode.setKey(key);
            cacheNode.setValue(value);
            nodesFIFO.put(key, cacheNode);
            if (lastFIFO != null) {
                lastFIFO.setNext(cacheNode);
                cacheNode.setFront(lastFIFO);
            }
            lastFIFO = cacheNode;
            if (firstFIFO == null) {
                firstFIFO = lastFIFO;
            }
        }
        //不等于空说明找到node 不进行操作
    }

    /**
     * 获取缓存中对象
     *
     * @param key 键
     * @return 对应Object
     */
    public Object get(K key) {
        CacheNode cacheNode = null;
        try {
            cacheNode = getCacheNode(key);
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
        return cacheNode == null ? -1 : cacheNode.getValue();
    }

    /**
     * 获取缓存中对象
     *
     * @param key 键
     * @return 对应CacheNode
     */
    private CacheNode getCacheNode(K key) throws ExecutionException, InterruptedException {

        CompletableFuture<CacheNode> cacheNodeCompletableFuture = CompletableFuture.supplyAsync(
                () -> {
                    if (firstLRU != null && firstLRU.getKey() == key) {
                        return firstLRU;
                        //本身就在第一个 不需要做移动
                    } else {
                        CacheNode node = nodesLRU.get(key);
                        if (node != null) {
                            //移动到第一个
                            moveToHead(node);
                            return node;
                        } else {
                            CacheNode node1 = nodesFIFO.get(key);
                            if (node1 != null) {
                                //从fifo队列删除 及fifo容器中删除
                                removeFIFO(node1);
                                //并添加到lru顶部 及lru链表顶部
                                putNodesLRU(node1);
                                return node1;
                            } else {
                                return null;
                            }
                        }
                    }
                });
        return cacheNodeCompletableFuture.get();
    }

    /**
     * 表示这个节点最近被使用 -> 移动到链表头
     *
     * @param nodeLRU 存放在LRU缓存容器中的node
     */
    private void moveToHead(CacheNode nodeLRU) {

        if (nodeLRU.getFront() != null) {
            //将nodeLRU的前一个的下一个指向nodeLRU的下一个
            nodeLRU.getFront().setNext(nodeLRU.getNext());
        }
        if (nodeLRU.getNext() != null) {
            //将nodeLRU的下一个的前一个指向nodeLRU前一个
            nodeLRU.getNext().setFront(nodeLRU.getFront());
        }
        if (lastLRU == nodeLRU) {
            //将尾部替换为lastLRU的上一个
            lastLRU = nodeLRU.getFront();
        }
        if (firstLRU != null) {
            nodeLRU.setNext(firstLRU);
            firstLRU.setFront(nodeLRU);
        }
        firstLRU = nodeLRU;
        //说明为链表头
        nodeLRU.setFront(null);
        if (lastLRU == null) {
            lastLRU = firstLRU;
            nodeLRU.setNext(null);
        }
    }

    /**
     * 从FIFO链表删除某一个node
     *
     * @param nodeFIFO 在FIFO中的node
     */
    private void removeFIFO(CacheNode nodeFIFO) {
        //从fifo容器中删除
        nodesFIFO.remove(nodeFIFO.getKey());
        if (lastFIFO == nodeFIFO) {
            if (lastFIFO.getFront() != null) {
                lastFIFO.getFront().setNext(null);
                lastFIFO = lastFIFO.getFront();
            } else {
                firstFIFO = null;
            }
            lastFIFO = nodeFIFO.getFront();
        } else {
            CacheNode index = lastFIFO.getFront();
            while (index != null) {
                if (index == nodeFIFO) {
                    if (index.getFront() != null) {
                        index.getFront().setNext(index.getNext());
                    } else {
                        firstFIFO = index.getNext();
                    }
                    index.getNext().setFront(index.getFront());
                    break;
                }
                //改变下标
                index = index.getFront();
            }
        }
    }

    /**
     * 第二次使用存入lru容器
     *
     * @param newNode 新的缓存node 从FIFO队列里拿出的node
     */
    private void putNodesLRU(CacheNode newNode) {
        newNode.setFront(null);
        newNode.setNext(null);
        if (firstLRU != null) {
            firstLRU.setFront(newNode);
            newNode.setNext(firstLRU);
        }
        firstLRU = newNode;
        //判断当前内存是否超过
        if (getCurrentSize() - initCacheSize > cacheSize) {
            if (lastLRU != null) {
                nodesLRU.remove(lastLRU.getKey());
                if (lastLRU.getFront() != null) {
                    lastLRU.getFront().setNext(null);
                } else {
                    //第一个也是最后一个
                    firstLRU = null;
                }
                lastLRU = lastLRU.getFront();
            }

        }
        nodesLRU.put(newNode.getKey(), newNode);
    }

    /**
     * 获得当前可用内存
     *
     * @return 可用内存
     */
    private Long getCurrentSize() {
        return Runtime.getRuntime().freeMemory();
    }

    private void setCacheSize() {
        //从配置文件中获取
        String cacheUnit = ConfigurationUtils.getString(GlobalConstants.MEMORY_CACHE_UNIT);
        Long cacheSize = Long.valueOf(ConfigurationUtils.getInteger(GlobalConstants.MEMORY_CACHE_SIZE));
        switch (cacheUnit) {
            case "gb":
                this.cacheSize = cacheSize * 1024 * 1024 * 1024;
                break;
            case "mb":
                this.cacheSize = cacheSize * 1024 * 1024;
                break;
            case "kb":
                this.cacheSize = cacheSize * 1024;
                break;
            case "GB":
                this.cacheSize = cacheSize * 1024 * 1024 * 1024;
                break;
            case "MB":
                this.cacheSize = cacheSize * 1024 * 1024;
                break;
            case "KB":
                this.cacheSize = cacheSize * 1024;
                break;
            default:
                log.error("缓存大小单位 " + cacheUnit + " 未识别,请使用kb mb gb");
                break;
        }
    }

    public void printLRUSortASC() {
        int count = 0;
        CacheNode next = firstLRU;
        while (next != null) {
            count++;
            System.out.println("LRU 第 " + count + " 个 key:" + next.getKey() + " value:" + next.getValue());
            next = next.getNext();
        }
    }

    public void printFIFOSortASC() {
        int count = 0;
        CacheNode next = firstFIFO;
        while (next != null) {
            count++;
            System.out.println("FIFO 第 " + count + " 个 key:" + next.getKey() + " value:" + next.getValue());
            next = next.getNext();
        }
    }
}

测试代码:

package dpnice.cache;

import org.junit.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static org.junit.Assert.*;

/**
 * @author DPn!ce   date 2018 07 13 下午 2:25
 */
public class FastCacheTest {
    private FastCache<String, String> fastCache = new FastCache<>();


    @Test
    public void put() throws Exception {
        fastCache.put("id1", "message:缓存的消息1");
        fastCache.put("id1", "message:缓存的消息1");
        fastCache.put("id2", "message:缓存的消息2");
        fastCache.put("id3", "message:缓存的消息3");
        fastCache.put("id4", "message:缓存的消息4");
        fastCache.put("id1", "message:缓存的消息1");
        fastCache.put("id2", "message:缓存的消息2");
        fastCache.put("id3", "message:缓存的消息3");
        fastCache.put("id4", "message:缓存的消息4");
        fastCache.put("id2", "message:缓存的消息2");
        fastCache.put("id2", "message:缓存的消息2");
//        Thread.sleep(2000L);
        System.out.println("id2 ->" + fastCache.get("id2"));
        System.out.println("id4 ->" + fastCache.get("id4"));
        System.out.println("id1 ->" + fastCache.get("id1"));
        System.out.println("id3 ->" + fastCache.get("id3"));

        fastCache.printLRUSortASC();

    }

    @Test
    public void get() throws Exception {
        System.out.println(fastCache.get("id2"));
        System.out.println(fastCache.get("id4"));
        System.out.println(fastCache.get("id1"));
        System.out.println(fastCache.get("id3"));
    }


    @Test
    public void put2() throws Exception {
        for (int i = 1; i < 5; i++) {
            fastCache.put("id" + i, "message:缓存的消息" + i);
        }
        //初始顺序: 4-3-2-1
        fastCache.printFIFOSortASC();
        //最近访问的在最顶部
        System.out.println(fastCache.get("id1"));
        System.out.println(fastCache.get("id3"));
        //预期顺序: LRU:3-1 FIFO:2-4
        fastCache.printLRUSortASC();
        fastCache.printFIFOSortASC();
    }

    @Test
    public void multithreadingTest() throws Exception {
        for (int i = 0; i < 10000; i++) {
            fastCache.put("id" + i, "message:缓存的消息" + i);
        }
       ExecutorService executor = Executors.newFixedThreadPool(10);
//        fastCache.printFIFOSortASC();
        //最近访问的在最顶部
        for (int i = 0; i < 1000000; i++) {
            executor.submit(() -> {
                Double v = Math.random() * 10000;
                String o = fastCache.get("id" + v.intValue()) + "";
//                System.out.println(o);
            });

        }
//        fastCache.printLRUSortASC();
//        fastCache.printFIFOSortASC();

    }

}

随机获取100W缓存结果:

散列表(下)-散列表和链表的组合 散列表和链表这两种数据结构经常被放到一起使用。比如 Redis 的有序集合不仅使用了跳表,还用了散列表。再比如 Java 语言中的 LinkedHashMap 容器,也用到了散列表和链表两种数据结构。 阅读详情

相关推荐

【信息科学与工程学】计算机科学与自动化——第八十一篇 Java分布式软件高并发/高可用算法01

4. 消息队列(如Kafka的Topic分区,本质是范围)。3. 若是ACCEPT事件,bossGroup线程接受连接,创建SocketChannel,并将其注册到workerGroup的一个EventLoop的Selector上,关注READ事件。1. 分布式缓存分片(如Redis Cluster)。4. 分布式文件存储(如Ceph CRUSH)。6. 调用栈的模拟(如协程)。3. 服务网格(如Istio)的基础。2. 本地缓存与集中式缓存(如Redis)的一致性维护。3. 静态数据(如配置)缓存。

weixin_49199313的博客 1229

Java8本地缓存Caffeine

文章目录一、Caffeine介绍1、缓存介绍2、Caffeine介绍二、Caffeine基础1、缓存加载策略1.1 Cache手动创建1.2 Loading Cache自动创建1.3 Async Cache异步获取2、驱逐策略3、刷新机制4、统计5、总结三、SpringBoot整合Caffeine1、@Cacheable相关注解1.1 相关依赖1.2 常用注解1.3 常用注解属性1.4 缓存同步模式2、实战2.1 引入依赖2.2 缓存常量CacheConstants2.3 缓存配置类CacheConfig2

Shawn的个人博客 1万+

主板USB接口全部失效解决方案(通用串行总线USB控制器有黄色叹号)保姆级教程亲测有效

通用串行总线控制器总是有叹号解决办法 办公室的崩腾时代老电脑,疫情期间没人用,来了开机之后发现鼠标键盘都用不了,本以为是主机放时间长出了问题,后来想起来就百度了“鼠标键盘都失效”的标题,结果发现了“串行总线控制器总是感叹号”的关联问题。正好办公室电脑都装有teamviwer常用来远程办公(在家偷懒)。所以通过远程发现电脑室可以运行的。并在控制面板发现:通用串行总线控制器总是感叹号,插入外设时USB无反应。如图:​ 并且右键选中其中一个,点击最后一个选项:“属性” 可以发现“设备状态”中会提示“由...

xiao_bai_0_0的博客 2万+

Java实现本地缓存的几种方式

Java实现本地缓存的几种方式

qinxun2008081的博客 1万+

C++笔试题整理

目录 1. 笔试题1 1.1 链表反转 1.2 String 2. 笔试题2 2.1 求下面函数的返回值(微软) 2.2 什么是“引用”?申明和使用“引用”要注意哪些问题? 2.3 将“引用”作为函数参数有哪些特点? 2.4 在什么时候需要使用“常引用”?  2.5 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则? 2.6 “引用”与多态的关系? 2.7 “引用”与指针的区别是什么? 2.8 什么时候需要“引用”? 2.9 结构与联合有和区别? 2.10 下面关于.

星月相随的专栏 2483

Web前端开发技术:实验14-16

实验14 1. 编写JavaScript程序实现“九九乘法口诀”表,如图14-40所示。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>九九乘法表</title> </head> <body> <h1>九九乘法表</h1> </body> <scri

KslgmrDry的博客 1万+

java高性能本地缓存_高性能本地缓存-caffeine

简介1、Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x) 后,spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件 2、支持异步加载,事件提交队列 3、内部使用W-TinyLFU算法,它的命中率非常高,内存占用更加的小 4、一般在redis之后,做二级缓存优势性能比较: 8个线程同时从缓存中读...

weixin_28738021的博客 780

零代码做游戏:AI辅助开发HTML5网页小游戏从创意到发布全流程

在软件开发领域,自然语言编程正成为一种新兴的人机协作方式,而AI辅助开发则是其最典型的落地形态。它让开发者无需精通语法,只需用清晰的语言描述游戏规则与交互逻辑,AI便能自动生成可运行的代码。这种模式大幅降低了编程门槛,尤其适合快速验证创意、制作原型。对于HTML5网页游戏而言,借助AI生成单个HTML文件,配合在线运行环境,即可在浏览器中直接试玩、迭代与分享。无论是产品经理验证玩法、运营人员制作互动小游戏,还是教育者设计课堂闯关,都能通过自然语言描述需求,让AI完成代码实现与报错修复。本文完整记录了一个“接

weixin_31497453的博客 329

【算法】缓存淘汰策略 及Java实现

1. LRU(Least Recently Used)最近最少使用 2. LFU(Least Frequently Used)最近最不经常使用 3. 近似LRU算法 4. TTL(Time To Live)超时时间 5. FIFO(First In First Out)先进先出 6. Random随机淘汰

dreambyday 760

图自编码器(GAE)与变分图自编码器(VGAE)

在学习图自编码器之前先了解一下自编码器与变分自编码器。

小鱼的小窝 1万+

微信小程序 - 详细实现随机生成订单号,微信小程序创建订单号思路,不重复订单号生成的方法,小程序自动生成固定规则的订单号流水号(必须是唯一不重复的订单号,生成唯一订单号)详细生成方法,示例代码教程最新

微信小程序,vue2,vue3,订单号,流水号思路,微信小程序 详细实现随机生成订单号(JavaScript),随机生成商户订单号,根据当前时间随机生成流水号或者订单号,微信小程序之商家订单,订单号随机生成器,自动生成固定规则的订单号(前缀+采购日期+6位流水号)微信小程序 生成外卖顺序号,生成订单号或流水号简单方法,实现订单号生成唯一的解决方案,如何按日期生成订单号,14位编号=8位日期(+6位流水号),自动生成订单号(固定+日期+数字),销售订单号自动生成。在微信小程序开发中,详解实现随机生成创建订单号

🏆 前端领域优质创作者 1186

Java使用LinkedHashMap实现LRU淘汰算法

什么是LRU LRU 是Least Recently Used的缩写,即最近最少使用,常用于页面置换算法。 在一般标准的操作系统教材里,会用下面的方式来演示 LRU 原理,假设内存只能容纳3个页大小,按照 7 0 1 2 0 3 0 4 的次序访问页。假设内存按照栈的方式来描述访问时间,在上面的,是最近访问的,在下面的是,最远时间访问的,LRU就是这样工作的。 LRU示意图 那么...

zgy956645239的博客 564

YOLOv8【第十一章:视频追踪与流处理篇·第16节】一文搞懂,DeepStream 部署入门:NVIDIA 视频分析 SDK 与 YOLOv8 结合!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。

**My Coding Family** 838

10道不得不会的缓存面试题【缓存】

缓存,就是数据交换的缓冲区,针对服务对象的不同(本质就是不同的硬件)都可以构建缓存。而我们平时说的缓存,大多是指内存。目的是,把读写速度【慢】的介质的数据保存在读写速度【快】的介质中,从而提高读写速度,减少时间消耗。CPU 高速缓存 :高速缓存的读写速度远高于内存。CPU 读数据时,如果在高速缓存中找到所需数据,就不需要读内存CPU 写数据时,先写到高速缓存,再回写到内存。磁盘缓存:磁盘缓存其实就把常用的磁盘数据保存在内存中,内存读写速度也是远高于磁盘的。读数据,时从内存读取。

JavaPub 5167

一次点击跑通:用 Postman 自动获取并携带 CSRF token,测试 SAP OData 写操作

SAP OData 写操作自动化测试方案 针对 SAP Gateway OData 服务写操作中常见的 CSRF token 验证问题,本文提出了一套基于 Postman 的自动化解决方案: 问题分析:解释了 CSRF token 的验证机制及其必要性,说明手工测试效率低下的原因 解决方案: 使用 Postman 环境变量存储 token 通过脚本自动获取并传递 token 利用 Collection Runner 实现一键执行 实施步骤: 创建环境变量存储 token 第一个请求获取 token 并存入变

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 304

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Redis之多级缓存设计详解

为什么要设计缓存呢? 其实高并发应对的解决方案不是互联网独创的,计算机先祖们很早就对类似的场景做了方案。比如《计算机组成原理》这样提到的cpu缓存概念,它是一种高速缓存,容量比内存小但是速度却快很多,这种缓存的出现主要是为了解决cpu运算速度远大于内存读写速度,甚至达到千万倍。 传统的cpu通过fsb直连内存的方式显然就会因为内存访问的等待,导致cpu吞吐量下降,内存成为性能瓶颈。同时又由于内存访...

qq_43107323的博客 8714

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

java截取固定大小图片_java缓存(三)——实现一个固定大小的对象缓存池

本文将介绍使用java语言实现一个对象缓存池。一步步的实现包括高速命中,固定大小的缓存队列等功能。这一期我们终于能够动手编写一些代码,使用java来实现一个在内存中的对象缓存池。不限大小的高速缓存池最开始的需求是实现一个能够在单线程模式下,根据唯一主键key来缓存对象的功能。对于java的集合类来说,能够得到近似的存取时间复杂度为O(1)的数据结构就是HashMap了,此处我们不再讲述其数据结构实...

weixin_36326528的博客 225

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

手机app应用分发网页https 对缓存的影响,app应用的缓存原理是什么如何解决?

用的HTTP协议成为另一个引起问题的协议。 HTTP协议可用于传输大小文件。同时,您可以使用高级功能,例如断点续传。许多FLASH浏览器使用HTTP协议进行视频播放。 如上所述,由于ISP之间的“跨网络支付”问题,某些地方(小型运营商,小区域)的服务器缓存HTTP请求。客户端:客户端http代理在服务器之间设置HTTP代理,解析HTTP请求并缓存请求的资源以存储跨网络计费。此处会出现一些问题,例如费用损失,错误的相应结果,错误的请求等。 大多数CDN供应商将服务器端日志用于计费目的。上述代理服务器可以通过

appmao的博客 445

如何设计分布式缓存系统?(含答案解析)

本文系统整理了Java分布式缓存面试核心知识,涵盖基础概念、架构设计、一致性策略和高可用方案。重点解析了缓存击穿/雪崩/穿透的解决方案、数据一致性策略(Cache Aside、Write-Through等)以及Redis集群高可用设计。提供典型面试题答案和Java操作Redis示例代码,帮助开发者深入理解分布式缓存技术要点。完整面试题库包含2000+题目,支持AI模拟面试和简历优化服务。

huazaijake的博客 468

多级缓存设计

为什么要设计缓存呢? 其实高并发应对的解决方案不是互联网独创的,计算机先祖们很早就对类似的场景做了方案。比如《计算机组成原理》这样提到的cpu缓存概念,它是一种高速缓存,容量比内存小但是速度却快很多,这种缓存的出现主要是为了解决cpu运算速度远大于内存读写速度,甚至达到千万倍。 传统的cpu通过fsb直连内存的方式显然就会因为内存访问的等待,导致cpu吞吐量下降,内存成为性能瓶颈。同时又由于内...

zombres的博客 1267

常见数据结构-散列表(下)散列表和链表的组合

散列表和链表这两种数据结构经常被放到一起使用。比如 Redis 的有序集合不仅使用了跳表,还用了散列表。再比如 Java 语言中的 LinkedHashMap 容器,也用到了散列表和链表两种数据结构。

专注计算机视觉算法训练,算法优化部署以及SDK开发的知识分享。 649

java内存加载状况监听_java程序员必须知道的内存知识-操作系统层

1.虚拟存储器作用1.为了给每个进程提供一致的地址空间(都从0开始),方便内存管理。2.保护每个进程的数据不会因为其它进程而被破坏。基于以上的原因,有了虚拟存储器,虚拟存储器是在硬盘上的一个文件,例如我们申请20G内存,其实只是在硬盘上创建了一个20g的文件,内存中只会有我们频繁读写的数据,换句话说内存是这个文件的缓存。这是一个32操作系统的虚拟存储器图结构为了对所有进程一致,下方是低地址从0开始...

weixin_29297127的博客 346

多级缓存设计详解 | 给数据库减负,刻不容缓!

关注我们获得更多内容作 者 简 介王梓晨物流研发部架构师,GIS 技术部负责人,2012 年加入京东,多年一线团队大促备战经验,负责物流研发一些部门的架构工作,专注于低延...

Enmotech的博客 1125

探秘Mycat-JCache:高性能缓存解决方案

探秘Mycat-JCache:高性能缓存解决方案 是一个基于Java的、与JCache(JSR-107)标准兼容的高效缓存系统,设计用于提升大型分布式应用的数据访问速度和响应性能。本文将深入探讨该项目的技术细节、应用场景及其独特优势,希望能吸引更多的开发者加入到Mycat-JCache的使用和开发中。 项目简介 Mycat-JCache是Mycat生态系统的一部分,Mycat是一个著名的开源数据库...

gitblog_00002的博客 398

数据结构习题三层价值:从算法思维到工程实战的进阶指南

数据结构是计算机科学的核心基础,它研究数据的组织、存储和操作方式,直接影响算法的效率与程序的性能。其核心原理在于通过抽象建模,将现实问题映射为可计算的数据关系,并利用特定结构的特性(如数组的随机访问、链表的动态增删、哈希表的快速查找)来优化操作。掌握数据结构的技术价值在于培养“将抽象问题映射到具体数据模型,并利用模型特性设计高效算法”的底层思维能力,这是区分代码实现者与问题解决者的关键。在实际应用场景中,这种能力不仅用于解决算法面试题,更贯穿于系统设计、性能优化和并发编程等工程实践。例如,在实现**LRU缓

weixin_34268579的博客 354
上一篇: Prometheus监控MySQL,Grafana展示
下一篇: docker 启动报错:Error starting daemon: SELinux is not supported with the overlay2 graph ...false)
DPnice
博客等级 码龄9年 38粉丝 63原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值