FIFO页面置换算法(先进先出)
基本思想
优先淘汰最早进入内存的页面,亦即在内存中驻留时间最久的页面。
该算法实现简单,
只需把调入内存的页面根据先后次序链接成队列,
我们知道队列的特性是先进先出
此时我们只需在需要置换的时候,出队队首元素就可以了
例题
假定系统为某进程分配了三个物理块,
并考虑有以下页面号引用串:7, 0, 1, 2, 0, 3, 0,4,2,3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1。
釆用FIFO算法进行页面置换,
进程访问页面2时,把最早进入内存的页面7换出。然后访问页面3时,再把2, 0, 1中最先进入内存的页换出。
由下图可以看出,利用FIFO算法时进行了12次页面置换。
访问页面 | 7 | 0 | 1 | 2 | 0 | 3 | 0 | 4 | 2 | 3 | 0 | 3 | 2 | 1 | 2 | 0 | 1 | 7 | 0 | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
物理块1 | 7 | 7 | 7 | 2 | 2 | 2 | 4 | 4 | 4 | 0 | 0 | 0 | 7 | 7 | 7 | |||||
物理块2 | 0 | 0 | 0 | 3 | 3 | 3 | 2 | 2 | 2 | 1 | 1 | 1 | 0 | 0 | ||||||
物理块3 | 1 | 1 | 1 | 0 | 0 | 0 | 3 | 3 | 3 | 2 | 2 | 2 | 1 | |||||||
缺页否 | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
具体实现
源代码
package 页面置换算法;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;
/**
* @author : YWJ
* @date : 2022/11/23 : 16:11
*/
/*
页面置换算法.FIFO 先进先淘汰
使用队列,先进先出的特点完成
每次进队一个
同时出队一个
*/
public class FIFO {
//队列
private static LinkedList<String> queue ;
//物理块个数
private static int physicalBlocks ;
//页面号引用串
private static String[] pageNumbers ;
//不缺页次数
private static int pagesNotMissCounts;
//页面置换次数 == 页面号引用串长度 - 物理块个数 - 不缺页次数
private static int replacementCounts ;
public static void main(String[] args) {
//物理块分配
blocksNums();
//页面号引用串初始
pageNumbersInitial();
//开始页面置换
pagesReplacement();
}
private static void blocksNums() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入分配物理块的个数:");
physicalBlocks = sc.nextInt();
}
private static void pageNumbersInitial() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入页面好引用串,页面之间使用空格隔开:");
pageNumbers = sc.nextLine().split("\\s+");
sc.close();
}
private static void pagesReplacement(){
queue = new LinkedList<>();
//开始循环遍历页码串,进行置换
for(String page : pageNumbers){
//只有当物理块为已占满,切当中不存在当前页码时,证明此时需要置换
if(queue.size() == 3 && !queue.contains(page)){
//出队队首元素,并入队当前页码
queue.remove();
queue.offer(page);
continue;
}
//剩下的情况也就是:一、物理块中已有当前页码
if(queue.contains(page)) {
//不缺页次数加一
pagesNotMissCounts ++ ;
continue;
}
// 二、物理块未占满,此时直接入队
queue.offer(page);
}
replacementCounts = pageNumbers.length-physicalBlocks-pagesNotMissCounts;
System.out.println("页面置换完成");
System.out.println("物理块个数:"+physicalBlocks);
System.out.println("页码串:"+ Arrays.toString(pageNumbers));
System.out.println("置换次数 :"+replacementCounts);
System.out.println("缺页次数 :"+(pageNumbers.length-pagesNotMissCounts));
}
}
执行结果
LRU页面置换算法(最近最少使用)
基本思想
如果数据最近被访问过,那么将来被访问的几率也更高。
当缓存队列已满时,新的元素加入队列时,需要从现有队列中移除一个元素,
LRU 策略就是将最近最少被访问的元素移除,
从而腾出空间给新的元素。
例题
依旧是FIFO的题,只不过换了一种算法
可以看到,每次把访问频率高的放在第一个位置
置换时,去掉访问次数最少的那个
访问页面 | 7 | 0 | 1 | 2 | 0 | 3 | 0 | 4 | 2 | 3 | 0 | 3 | 2 | 1 | 2 | 0 | 1 | 7 | 0 | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
物理块1 | 1 | 2 | 0 | 3 | 0 | 4 | 2 | 3 | 0 | 3 | 2 | 1 | 2 | 0 | 1 | 7 | 0 | 1 | ||
物理块2 | 0 | 0 | 1 | 2 | 0 | 3 | 0 | 4 | 2 | 3 | 0 | 3 | 2 | 1 | 2 | 0 | 1 | 7 | 0 | |
物理块3 | 7 | 7 | 7 | 0 | 1 | 2 | 2 | 3 | 0 | 4 | 2 | 2 | 0 | 3 | 3 | 1 | 2 | 0 | 1 | 7 |
缺页否 | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
算法实现
源代码
package 页面置换算法;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;
/**
* @author : YWJ
* @date : 2022/11/27 : 17:12
*/
public class LRU {
//队列
private static LinkedList<String> queue ;
//辅助队列
private static LinkedList<String> auxiliary ;
//物理块个数
private static int physicalBlocks ;
//页面号引用串
private static String[] pageNumbers ;
//不缺页次数
private static int pagesNotMissCounts;
//页面置换次数 == 页面号引用串长度 - 物理块个数 - 不缺页次数
private static int replacementCounts ;
public static void main(String[] args) {
//物理块分配
blocksNums();
//页面号引用串初始
pageNumbersInitial();
//开始页面置换
pagesReplacement();
}
private static void blocksNums() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入分配物理块的个数:");
physicalBlocks = sc.nextInt();
}
private static void pageNumbersInitial() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入页面好引用串,页面之间使用空格隔开:");
pageNumbers = sc.nextLine().split("\\s+");
sc.close();
}
private static void pagesReplacement(){
queue = new LinkedList<>();
//开始循环遍历页码串,进行置换
for(String page : pageNumbers){
auxiliary = new LinkedList<>();
//只有当物理块为已占满,切当中不存在当前页码时,证明此时需要置换
if(queue.size() == 3 && !queue.contains(page)){
//出队队首元素,并入队当前页码
queue.remove();
queue.offer(page);
continue;
}
//否则,两种情况 一、物理块已有当前页码
if(queue.contains(page)){
/*
此时我们需要移除原本的页码,并重新将他添加到队尾
此时只需要借助一个辅助队列
*/
for (int i = 0; i < queue.size(); ) {
if(!page.equals(queue.peek())){
auxiliary.offer(queue.remove());
}else {
queue.remove();
}
}
queue = auxiliary;
queue.offer(page);
//不缺页次数加一
pagesNotMissCounts ++ ;
continue;
}
//二、物理块未满,直接入队
queue.offer(page);
}
replacementCounts = pageNumbers.length-physicalBlocks-pagesNotMissCounts;
System.out.println("页面置换完成");
System.out.println("物理块个数:"+physicalBlocks);
System.out.println("页码串:"+ Arrays.toString(pageNumbers));
System.out.println("置换次数 :"+replacementCounts);
System.out.println("缺页次数 :"+(pageNumbers.length-pagesNotMissCounts));
}
}