You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LRU缓存模拟器运行异常求助:仅显示首个输入值,其余为0

LRU缓存模拟器问题排查与修复

我正在实现一个基于LRU替换策略的简易缓存模拟器,但输入引用字符串后,缓存仅显示第一个输入的数值,其余位置均为0,无法按照LRU策略正确添加数据。

代码

package cacheProject;

import java.util.Scanner;
public class cacheProject {

   private int numBlocks;
   private int setAssoc;
   private String replacementPolicy;
   public cacheProject(int numBlocks, int setAssoc, String replacementPolicy) {
       this.numBlocks = numBlocks;
       this.setAssoc = setAssoc;
       this.replacementPolicy = replacementPolicy;
   }
   public void simulate(int[] references) {
       int missRate = 0;
       int hits = 0;
       int[] cache = new int[numBlocks];
       for (int i = 0; i < references.length; i++) {
           int block = references[i];
           // check if block is in cache
           boolean inCache = false;
           for (int j = 0; j < cache.length; j++) {
               if (cache[j] == block) {
                   inCache = true;
                   hits++;
                   break;
               }
           }
           // if not in cache, add it
           if (!inCache) {
               missRate++;
               // if cache is full, remove LRU block
               if (cache[numBlocks - 1] != 0) {
                   int lruBlock = findLRUBlock(cache);
                   cache[lruBlock] = 0;
               }
               // add new block to cache
               for (int j = 0; j < cache.length; j++) {
                   if (cache[j] == 0) {
                       cache[j] = block;
                       break;
                   }
               }
           }
       }
       System.out.println("Miss rate: " + (double) missRate / references.length);
       System.out.println("Hits: " + hits);
       System.out.println("Cache contents:");
       for (int i = 0; i < cache.length; i++) {
           System.out.print(cache[i] + " ");
       }
       System.out.println();
   }
   public int findLRUBlock(int[] cache) {
       if (replacementPolicy.equals("LRU")) {
           int lruBlock = 0;
           int lruTime = Integer.MAX_VALUE;
           for (int i = 0; i < cache.length; i++) {
               int time = 0;
               for (int j = 0; j < cache.length; j++) {
                   if (cache[i] == cache[j]) {
                       time++;
                   }
               }
               if (time < lruTime) {
                   lruBlock = i;
                   lruTime = time;
               }
           }
           return lruBlock;
       }
       return -1;
   }
   public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
       System.out.print("Enter number of cache blocks: ");
       int numBlocks = in.nextInt();
       System.out.print("Enter set associativity (1=direct mapped, 2=2-way, 4=4-way): ");
       int setAssoc = in.nextInt();
       System.out.print("Enter replacement policy (FIFO or LRU): ");
       String replacementPolicy = in.next();
       cacheProject cache = new cacheProject(numBlocks, setAssoc, replacementPolicy);
       System.out.println("Enter reference string:");
       String input = in.next();
       String[] references = input.split(" ");
       int[] refs = new int[references.length];
       for (int i = 0; i < references.length; i++) {
           refs[i] = Integer.parseInt(references[i]);
       }
       cache.simulate(refs);
   }
}

实际输出

Enter number of cache blocks: 5
Enter set associativity (1=direct mapped, 2=2-way, 4=4-way): 1
Enter replacement policy (FIFO or LRU): LRU
Enter reference string:
3 4 3 5 4 3 5
Miss rate: 1.0
Hits: 0
Cache contents:
3 0 0 0 0

预期输出

Enter number of cache blocks: 5
Enter set associativity (1=direct mapped, 2=2-way, 4=4-way): 1
Enter replacement policy (FIFO or LRU): LRU
Enter reference string:
3 4 3 5 4
Miss rate: 1.0
Hits: 0
Cache contents:
3 4 3 5 4

问题原因与修复

1. 引用字符串读取错误

Scanner.next()只会读取空格前的第一个字符串,导致输入的多值引用串仅被读取第一个数值,后续数据全部丢失。修改main方法中的读取逻辑:

System.out.println("Enter reference string:");
in.nextLine(); // 消耗之前nextInt()留下的换行符
String input = in.nextLine();
String[] references = input.split(" ");

2. LRU核心逻辑错误

原findLRUBlock方法通过统计缓存块值的重复次数判断LRU,完全违背了LRU(最近最少使用)的核心逻辑——需要跟踪每个缓存块的最近使用时间戳。修复后的simulate方法:

public void simulate(int[] references) {
    int missCount = 0;
    int hitCount = 0;
    int[] cache = new int[numBlocks];
    int[] lastUsedTime = new int[numBlocks]; // 记录每个块的最后使用时间
    int currentTime = 0;

    for (int i = 0; i < references.length; i++) {
        currentTime++;
        int block = references[i];
        boolean inCache = false;
        int hitIndex = -1;

        // 检查缓存命中
        for (int j = 0; j < cache.length; j++) {
            if (cache[j] == block) {
                inCache = true;
                hitCount++;
                hitIndex = j;
                break;
            }
        }

        if (inCache) {
            // 命中时更新该块的使用时间
            lastUsedTime[hitIndex] = currentTime;
        } else {
            missCount++;
            int emptyIndex = -1;
            // 寻找空缓存块
            for (int j = 0; j < cache.length; j++) {
                if (cache[j] == 0) {
                    emptyIndex = j;
                    break;
                }
            }

            if (emptyIndex != -1) {
                // 有空位直接放入
                cache[emptyIndex] = block;
                lastUsedTime[emptyIndex] = currentTime;
            } else {
                // 无空位时找LRU块(时间戳最小的)
                int lruIndex = 0;
                int minTime = Integer.MAX_VALUE;
                for (int j = 0; j < lastUsedTime.length; j++) {
                    if (lastUsedTime[j] < minTime) {
                        minTime = lastUsedTime[j];
                        lruIndex = j;
                    }
                }
                // 替换LRU块
                cache[lruIndex] = block;
                lastUsedTime[lruIndex] = currentTime;
            }
        }
    }

    // 输出结果
    System.out.println("Miss rate: " + (double) missCount / references.length);
    System.out.println("Hits: " + hitCount);
    System.out.println("Cache contents:");
    for (int val : cache) {
        System.out.print(val + " ");
    }
    System.out.println();
}

3. 缓存满的判断逻辑错误

原代码通过cache[numBlocks - 1] != 0判断缓存是否已满,仅适用于顺序填充场景,若中间有空位(替换后)会判断错误。修复后改为先寻找空位,找不到再执行替换逻辑,无需额外判断缓存状态。

内容的提问来源于stack exchange,提问作者deadpanrobo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 13:10:32