java实现操作系统中的最佳置换Optimal算法

Java实现操作系统中的最佳置换Optimal算法攻略

算法介绍

最佳置换算法(Optimal)也称为理论最优算法。其思想是根据还未完成的进程未来的使用情况,计算出每一个进程在什么时候会访问页面,然后选择最长时间以后才用到的页面进行置换。

实现步骤

  1. 首先根据需要分配的内存大小,将所有的物理块置为空闲状态,并初始化所有页面的最近使用时间为正无穷大。
  2. 当一个新页面需要进入物理块时,检查空闲块,如果有则直接分配。如果没有空闲块,我们需要检查将要置换的页,选择预计最长时间未被使用的页进行置换。
  3. 遍历所有getPageList()页面,记录每个页面下一次的使用时间(找到下一个访问时间最大的页)。
  4. 比较每一页最近的下次使用时间,选择将距离下一次访问时间最远的页面进行替换,将其写入磁盘、更新页面表与页表即可。
  5. 重复上述步骤,直到完成所有的分配请求。

Java代码

import java.util.*;

class OptimalPageReplacement {

    private final List<Integer> getPageList() {
        // 内部页面列表,根据任务中定义方式生成
        return Arrays.asList(1, 2, 3, 2, 4, 5, 6, 7, 6, 8, 7, 8, 9, 7, 8, 9, 5, 4, 5, 4, 2);
    }

    private final void replacePages(int numFrames) {
        List<Integer> pageList = getPageList();
        List<Integer> frames = new ArrayList<>();
        Map<Integer, Integer> nextOccurrences = new HashMap<>();
        int pageFault = 0;
        for (int i = 0; i < numFrames; i++) {
            frames.add(-1);
        }
        for (int i = 0; i < pageList.size(); i++) {
            int currentPage = pageList.get(i);
            int frameIndex = frames.indexOf(currentPage);
            if (frameIndex != -1) {
                System.out.println("Request for page " + currentPage + " already found in Frame " + frameIndex);
                continue;
            }
            System.out.println("Request for page " + currentPage + " not found");
            if (frames.contains(-1)) {
                int emptyFrameIndex = frames.indexOf(-1);
                frames.set(emptyFrameIndex, currentPage);
                System.out.println("Page " + currentPage + " allocated to empty frame " + emptyFrameIndex);
                nextOccurrences.put(currentPage, getNextOccurrence(pageList, i));
                continue;
            }
            int replacement = getNextToReplace(frames, nextOccurrences);
            int replacedPageIndex = frames.indexOf(replacement);
            frames.set(replacedPageIndex, currentPage);
            nextOccurrences.put(currentPage, getNextOccurrence(pageList, i));
            System.out.println("Page " + replacement + " replaced with page " + currentPage + " in Frame " + replacedPageIndex);
            pageFault++;
        }
        System.out.println("Total Page Faults:" + pageFault);
    }

    private final int getNextOccurrence(List<Integer> pageList, int currentPageIndex) {
        for (int i = currentPageIndex + 1; i < pageList.size(); i++) {
            if (pageList.get(i) == currentPageIndex) {
                return i;
            }
        }
        return pageList.size() + 1;
    }

    private final int getNextToReplace(List<Integer> frames, Map<Integer, Integer> nextOccurrences) {
        int max = -1;
        int replace = -1;
        for (int i = 0; i < frames.size(); i++) {
            int currentPage = frames.get(i);
            if (!nextOccurrences.containsKey(currentPage)) {
                return i;
            } else {
                if (nextOccurrences.get(currentPage) > max) {
                    max = nextOccurrences.get(currentPage);
                    replace = i;
                }
            }
        }
        return replace;
    }

    public static void main(String[] args) {
        OptimalPageReplacement opr = new OptimalPageReplacement();
        opr.replacePages(3);
    }
}

示例说明

示例1

在这个示例中,CPU占用一个包含3个物理页面的系统。对于这类小系统,函数的执行顺序取决于输入的页请求序列。

  • 请求页1。在请求1时,物理块是空的。第一个页面被分配到物理块0。
  • 请求页2。在请求2时,物理块中没有空的物理块。在这种情况下,根据Optimal算法,算法分配被分配最长时间周期内没有使用的页面。在这种情况下,即使整个未来将使用的时间取决于请求码,但最佳可用的物理块是0。这意味着物理块1和2分别为1和2,从而执行相应的页面错误。
  • 请求页3。在请求3时,物理块0和1都包含了一个页面。但是页面3并不在主存中。在这种情况下,根据Optimal算法,算法为3分配被分配最长时间周期内没有使用的页面。在这种情况下,optimal算法将页面0和1中的任意一个页面替换为页面3。此时,选择可以替换的页面是0,因为在页面调用链中,最长的时间为7。
  • 请求页2。在请求2时,物理块1和2分别为1和2。因此,找到页面2,因此不需要将当前所需的任何页面替换掉。
  • 请求页4。在请求4时,页面4并不在主存中。此时的页面分配情况为(2,1,0)。在这种情况下,算法使用有最长使用时间的页面(在这种情况下,页面1的下一个访问将在9次调用后进行,而其他页面的下一个访问在5和8次之后)。此时,可以替换的页面是页面0或页面2。因为页面0有更长的时间或未使用,因此将页面4换掉,并将新的页面0放入物理块0中。
  • 请求5。请求5时,页面5不在物理块中。此时的页面分配情况为(4,1,5)。在这种情况下,根据Optimal算法,使用拥有最长时间段的页面分配,因为希望在页面请求依赖关系中尽可能长时间地放置当前要求。在这种情况下,页面1的下一个使用周期最长。这时可以替换的页面是页面0或页面2。因为页面0比页面2下一个使用时间更长(页2应该在6次访问以后),页面0被替换为页面5。因此,页面分配变成了(5, 1, 4)。
  • 请求页6。在请求6时,可以替换的页面是页面4或页面1。然而,因为页面1比页面4下一个使用时间长,因此页面1被替换为页面6。此时,物理块分配变成了(5, 6, 4)。

示例2

在这个示例中,CPU占用一个包含3个物理页面的系统。

  • 请求页3.页面调入位于物理块0。
  • 请求页2.页面调入位于物理块1。
  • 请求页4。页面调入位于物理块2。
  • 请求页6。发现所有物理块都已经分配出去了,根据Optimal算法,要查找下一个将要被使用的页,发现所有人将在未来无限的某个时刻被使用。按顺序每个页面都被标记以寻找将来访问的页面,在这个例子中,唯一不同的是一个页面标记解封期间是很近的,这个页面将会被换出物理块。页面4被替换为页面6,物理块分配变成(3, 2, 6)。
  • 请求页2。因为页面2已经在物理块中了,因此不需要置换。
  • 请求页4。因为页面4已经在物理块中了,因此不需要置换。
  • 请求页3。此时物理块内所有页面都已经被使用,需要选择一个最佳页面移除。需要整个页面序列来算法,以查找下一个每个页面将被访问的时间。由于所有页面都曾经出现过,所以算法无法从物理块中移除任何页面。

因此,总共有1个页面错误。

总结

Optimal算法是一种最佳的估计算法,旨在像未来一样分配对于所有物理/虚拟页面调用快照都最优。尽管在实际情况下无法预测所有请求,但它仍然作为理论原型被使用。由于它是一种最佳的算法,因此在实际情况下可能不太可能出现不同的结果。在一些情况下,其他算法例如LRU可能会提供更好的结果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java实现操作系统中的最佳置换Optimal算法 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 使用maven shade插件解决项目版本冲突详解

    使用Maven Shade插件可以将所有的依赖包、类库和所需的资源打包到一个可执行的Jar文件中,从而避免在运行时出现项目版本冲突的问题。以下是使用Maven Shade插件解决项目版本冲突的完整攻略: 环境要求 JDK 1.8+ Maven 3.x+ 使用Maven Shade插件 在pom.xml文件中添加以下配置: <build> <…

    Java 2023年5月20日
    00
  • 详解如何在Java中调用Python程序

    完整攻略如下: 1. 安装Jython Jython是Python的一种实现,它可以与Java无缝集成。因此,在Java中调用Python程序要用到Jython。可以从Jython官网下载Jython的最新版本。安装完成后,需要将Jython的安装路径配置到Java的环境变量中。 2. 创建Python程序 首先,编写一个简单的Python程序,例如: # …

    Java 2023年5月23日
    00
  • 详解Android客户端与服务器交互方式

    非常感谢您对Android客户端与服务器交互方式的关注。在此给您详细讲解Android客户端与服务器交互方式的攻略。 什么是Android客户端与服务器交互? Android客户端与服务器交互是指在Android手机上使用网络协议与服务器进行数据交互的过程。这种交互方式被广泛应用在Android应用程序的开发中,比如基于网络服务的即时通讯、电商 App 中的…

    Java 2023年5月19日
    00
  • Java springboot接口迅速上手,带你半小时极速入门

    Javaspringboot接口迅速上手,带你半小时极速入门攻略 什么是Spring Boot Spring Boot是Spring框架的扩展,使得开发者可以更加方便快捷地创建Spring Web应用和微服务应用。Spring Boot提供了很多自动化配置,通过使用Spring Boot可以快速搭建一个现代化的Web应用或者是微服务。 开始使用Spring …

    Java 2023年5月15日
    00
  • Maven默认使用JDK1.5的问题及解决方案

    Maven 是 Java 项目管理的常用工具,它默认使用 JDK 1.5 的编译器插件,但是在实际开发中可能需要使用更高版本的 JDK,因此需要解决 Maven 默认使用 JDK 1.5 的问题。接下来我们将介绍详细的解决方案。 问题描述 在使用 Maven 时,默认情况下会使用 JDK 1.5 的编译器插件进行项目的编译。如果我们需要使用 JDK 1.6 …

    Java 2023年5月20日
    00
  • Spring Cloud Feign统一设置验证token实现方法解析

    下面我将详细讲解“Spring Cloud Feign统一设置验证token实现方法解析”的完整攻略。 1. 背景 在微服务架构中,服务之间的通信非常频繁,而服务的鉴权机制也非常重要。通常情况下,服务之间会使用 token 鉴权,而 token 的生成和验证会依赖于后端的认证服务。针对这种场景,我们可以使用 Spring Cloud Feign 统一设置验证…

    Java 2023年6月15日
    00
  • 一篇超详细的Spring Boot对jdbc支持的文章

    下面是我对这个主题的完整攻略: 一、简介 在介绍 Spring Boot 对 JDBC 支持的同时,我们需要先了解 JDBC 是什么。JDBC (Java DataBase Connectivity) 是 Java 语言中操作关系型数据库的 API。Spring Boot 建立在 Spring 框架的基础之上,因此 Spring Boot 是通过 Sprin…

    Java 2023年5月20日
    00
  • 从源码角度深入解析Callable接口

    摘要:从源码角度深入解析Callable接口,希望大家踏下心来,打开你的IDE,跟着文章看源码,相信你一定收获不小。 本文分享自华为云社区《一个Callable接口能有多少知识点?》,作者: 冰 河。 并发编程一直是程序员们比较头疼的,如何编写正确的并发程序相比其他程序来说,是一件比较困难的事情,并发编程中出现的 Bug 往往也是特别诡异的。 之所以说并发编…

    Java 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部