java实现:《操作系统实验三》模拟内存管理

2023-11-13

固定分区分配

固定分区分配是最简单的一种多道程序存储管理方式,它将用户内存空间划分为若干个固定大小的区域,每个分区只装入一道作业。当有空闲分区时,便可以再从外存的后背作业队列中,选择适当大小的作业装入该分区,如此循环。

在这里插入图片描述
在这里插入图片描述

优缺点:

分区大小相等:用于利用一台计算机控制多个相同对象的场合,缺乏灵活性
分区大小不等:划分为含有多个较小的分区,适量的中等分区及少量的大分区。
优点:1.没有外部碎片
缺点:1.程序可能太大而放不进任何一个分区中,这时用户不得不使用覆盖技术来使用内存空间。
主存利用率低,当程序小于固定分区大小时,也占用一个完整的内存分区空间,这样分区内部有空间浪费,这种现象称为内部碎片。
不能多个进程共享一个主存区

#java模拟实现:

package com.qiu;

import java.util.Collections;
import java.util.Date;

public class mem_a extends Thread{
	public char[] mem;
	//定义内存大小
	public mem_a(int size) {
		mem=new char[size];
		for(int i=0;i<size;i++) {
			mem[i]='_';
		}
	}
	
	@Override
	public void run() {
		while(true) {
			try {
				/**Collections工具类中的nCopies(int n,T o)方法用于返回一个不可变列表组成的n个拷贝的指定对象。
				 * 此处即是将"/n"拷贝100次并以字符串形式放回(模拟内存的读写过程中间的页面刷新)
				 * */
				System.out.println(Collections.nCopies(100, "\n").stream().reduce((a, b)->a+b).get());
				//s1为模拟内存逻辑地址,初始状态还未分配资源全为‘_’
				StringBuffer s1=new StringBuffer("[");
				for(int i=0;i<mem.length;i++) {
					s1.append(mem[i]);
				}
				s1.append("]");
				//s2模拟内存分区大小
				StringBuffer s2=new StringBuffer("[1");
				for(int i=1;i<mem.length-1;i++) {
					s2.append('_');
					if(mem[i]!=mem[i+1]&&i!=0) {
						s2.append(i+1);
						i+=(i+"").length();
					}
				}
				s2.append(mem.length+"]");
				System.out.println(new Date());
				System.out.println(s1);
				System.out.println(s2);
				Thread.sleep(100);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
	//分配内存方法
	public void allocate(char key,int start,int length) {
		for(int i=start;i<start+length;i++) {
			mem[i]=key;
		}
	}
	//释放内存方法
	public void free(char key) {
		for(int i=0;i<mem.length;i++) {
			if(mem[i]==key) {
				mem[i]='_';
			}
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		mem_a m=new mem_a(100);
		m.start();
		
		Thread.sleep(3000);
		m.allocate('a', 0, 30);
		Thread.sleep(3000);
		m.allocate('b', 40, 20);
		Thread.sleep(3000);
		m.allocate('a', 80, 20);
		Thread.sleep(3000);
		m.free('b');
		
	}
}

动态分区分配

动态分区分配又称为可变分区分配。这种分配方式不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要。因此系统分区的大小和数目是可变的。
在这里插入图片描述

首次适应算法

算法思想:每次都从低地址开始查找,找到第–个能满足大小的空闲分区。

如何实现:空闲分区以地址递增的次序排列。每次分配内存时顺序查找空闲分区链( 或空闲分[表),找到大小能满足要求的第-一个空闲分区。

在这里插入图片描述
java实现:

package com.qiu;

import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;

public class mem_b extends Thread{
	public char[] mem;
	//定义内存大小
	public mem_b(int size) {
		mem=new char[size];
		for(int i=0;i<size;i++) {
			mem[i]='_';
		}
	}

	@Override
	public void run() {
		while(true) {
			try {
				/**Collections工具类中的nCopies(int n,T o)方法用于返回一个不可变列表组成的n个拷贝的指定对象。
				 * 此处即是将"/n"拷贝100次并以字符串形式放回(模拟内存的读写过程中间的页面刷新)
				 * */
				System.out.println(Collections.nCopies(100, "\n").stream().reduce((a, b)->a+b).get());
				//s1为模拟内存逻辑地址,初始状态还未分配资源全为‘_’
				StringBuffer s1=new StringBuffer("[");
				for(int i=0;i<mem.length;i++) {
					s1.append(mem[i]);
				}
				s1.append("]");
				//s2模拟内存分区大小
				StringBuffer s2=new StringBuffer("[1");
				for(int i=1;i<mem.length-1;i++) {
					s2.append('_');
					if(mem[i]!=mem[i+1]&&i!=0) {
						s2.append(i+1);
						i+=(i+"").length();
					}
				}
				s2.append(mem.length+"]");
				System.out.println(new Date());
				System.out.println(s1);
				System.out.println(s2);
				Thread.sleep(100);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	int lastpos=0;
	LinkedList<Character> waitkey=new LinkedList<>();
	LinkedList<Integer> waitSize=new LinkedList<>();
	
	public boolean allocate(char key,int size) {
		int freemem=0,begin=lastpos;
		boolean quit=false;
		while(true) {
			if(mem[lastpos]=='_') {
				freemem++;
				if(freemem==size) {
					lastpos++;
					for(int i=0;i<size;i++) {
						mem[(i+lastpos-size+mem.length)%mem.length]=key;
					}
					return true;
				}
			}else {
				freemem=0;
				if(quit) {
					break;
				}
			}
			lastpos=(++lastpos)%mem.length;
			if(lastpos==begin) {
				quit=true;
			}
		}
		waitkey.push(key);
		waitSize.push(size);
		return false;
	}
	
	public void free(char key) {
		for(int i=0;i<mem.length;i++) {
			if(mem[i]==key) {
				mem[i]='_';
			}
		}
		int waitnum=waitkey.size();
		for(int i=0;i<waitnum;i++) {
			allocate(waitkey.poll(),waitSize.poll());
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		mem_b m=new mem_b(100);
		m.start();
		Thread.sleep(3000);
		m.allocate('a', 30);
		Thread.sleep(3000);
		m.allocate('b', 40);
		Thread.sleep(3000);
		m.allocate('c', 50);
		Thread.sleep(3000);
		m.allocate('d', 20);
		Thread.sleep(3000);
		m.free('a');
		Thread.sleep(3000);
		m.free('d');
		
	}
}	

最佳适应算法

算法思想:由于动态分区分配是一种连续分配方式,为各进程分配的空间必须是连续的一整片区域。因此为了保证当“大进程”到来时能有连续的大片空间,可以尽可能多地留下大片的空闲区,即,优先使用更小的空闲区。

如何实现:空闲分区按容量递增次序链接。每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第-一个空闲分区。
在这里插入图片描述
java实现:

package com.qiu;

import javafx.util.Pair;

import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedList;

public class mem_c extends Thread{
    public char[] mem;
    //定义内存大小
    public mem_c(int size) {
        mem=new char[size];
        for(int i=0;i<size;i++) {
            mem[i]='_';
        }
    }

    @Override
    public void run() {
        while(true) {
            try {
                /**Collections工具类中的nCopies(int n,T o)方法用于返回一个不可变列表组成的n个拷贝的指定对象。
                 * 此处即是将"/n"拷贝100次并以字符串形式放回(模拟内存的读写过程中间的页面刷新)
                 * */
                System.out.println(Collections.nCopies(100, "\n").stream().reduce((a, b)->a+b).get());
                //s1为模拟内存逻辑地址,初始状态还未分配资源全为‘_’
                StringBuffer s1=new StringBuffer("[");
                for(int i=0;i<mem.length;i++) {
                    s1.append(mem[i]);
                }
                s1.append("]");
                //s2模拟内存分区大小
                StringBuffer s2=new StringBuffer("[1");
                for(int i=1;i<mem.length-1;i++) {
                    s2.append('_');
                    if(mem[i]!=mem[i+1]&&i!=0) {
                        s2.append(i+1);
                        i+=(i+"").length();
                    }
                }
                s2.append(mem.length+"]");
                System.out.println(new Date());
                System.out.println(s1);
                System.out.println(s2);
                Thread.sleep(100);
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    LinkedList<Character> waitkey=new LinkedList<>();
    LinkedList<Integer> waitSize=new LinkedList<>();
    /*
     * java Pair类的使用场景:
     * 当我们在写一个方法需要返回两个字段值时,我之前的方法是新建一个类或使用集合。目前来看使用Pair方便很多。
             配对(Pair)。配对提供了一种方便方式来处理简单的键值关联,当我们想从方法返回两个值时特别有用。
     */
    LinkedList<Pair<Integer,Integer>> size_start=new LinkedList<>();

    public void updateFreeList() {
        size_start.clear();
        int freecount=0;
        for(int i=0;i<mem.length;i++) {
            if(mem[i]=='_') {
                freecount++;
            }else {
                if(freecount>0) {
                    size_start.add(new Pair<Integer,Integer>(freecount,i-freecount));
                    freecount=0;
                }
            }
        }
        if(freecount>0) {
            size_start.add(new Pair<Integer,Integer>(freecount,mem.length-freecount));
            freecount=0;
        }
        Collections.sort(size_start,new Comparator<Pair<Integer,Integer>>(){
            public int compare(Pair<Integer,Integer> o1,Pair<Integer,Integer> o2) {
                return o1.getKey()-o2.getKey();
            };
        });
    }
    public boolean allocate(char key,int size) {
    	updateFreeList();
        boolean quit=false;
        for(Pair<Integer,Integer> entry:size_start) {
            if(entry.getKey()>=size) {
                for(int i=0;i<size;i++) {
                    mem[entry.getValue()+i]=key;
                }
                updateFreeList();
                quit=true;
                break;
            }
        }
        if(!quit) {
            waitkey.push(key);
            waitSize.push(size);
        }
        return quit;
    }

    public void free(char key) {
        for(int i=0;i<mem.length;i++) {
            if(mem[i]==key) {
                mem[i]='_';
            }
        }
        int waitnum=waitkey.size();
        for(int i=0;i<waitnum;i++) {
            allocate(waitkey.poll(),waitSize.poll());
        }
    }
    public static void main(String[] args) throws InterruptedException {
        mem_c m=new mem_c(100);
        m.start();
        Thread.sleep(3000);
        m.allocate('a', 30);
        Thread.sleep(3000);
        m.allocate('b', 40);
        Thread.sleep(3000);
        m.allocate('c', 50);
        Thread.sleep(3000);
        m.allocate('d', 20);
        Thread.sleep(3000);
        m.free('a');
        Thread.sleep(3000);
        m.free('d');
        Thread.sleep(3000);
        m.allocate('e', 30);
    }
}

关于第三种方式在Eclipse上编译报错的解决方法:

原因:Pair类 javafx.util.Pair无法找到
解决方法:
window->Perferences
在这里插入图片描述
之后再次运行,便ok了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java实现:《操作系统实验三》模拟内存管理 的相关文章

  • C# 与 JAVA 接口实例

    我不知道该如何回答我的问题 它是关于Android可以实例化接口的 我正在尝试用 C 来做 现在我非常确定 Java 和 C 的规则是不能创建抽象和接口的实例 但我很想知道Android是如何做到这一点的 在 Android 中你可以这样做
  • Java中如何合并两个数组?

    它不是连接而是合并两个数组 使它们成为名称值对的数组 firstarray a aa aaa secondarray b bb bbb result a b aa bb aaa bbb 最好的方法是什么 in Java public sta
  • 将键与多个值对象关联的有效集合[重复]

    这个问题在这里已经有答案了 有任何有效的集合可以将键与多个值关联起来 例如 new HashMap
  • Java中的字节和字符转换

    如果我将一个字符转换为byte然后回到char 那个角色神秘地消失了 变成了别的东西 这怎么可能 这是代码 char a line 1 byte b byte a line 2 char c char b line 3 System out
  • 如何访问EmbeddedSolrServer实例的管理界面?

    在我的网络应用程序中 我正在运行org apache solr client solrj embedded EmbeddedSolrServer出于调试目的 我想访问管理界面 这就是我实例化服务器的方式 new EmbeddedSolrSe
  • 参考接口创建对象

    引用变量可以声明为类类型或接口类型 如果变量声明为接口类型 则它可以引用实现该接口的任何类的任何对象 根据上面的说法我做了一个理解上的代码 正如上面所说声明为接口类型 它可以引用实现该接口的任何类的任何对象 但在我的代码中显示display
  • Java:从 ScriptEngine javascript 返回一个对象

    我正在尝试使用 Java 来评估 javascript脚本引擎 https docs oracle com javase 7 docs api javax script ScriptEngine html班级 这是我正在尝试做的事情的一个简
  • Java 套接字 - 读和写

    问题 客户端没有收到任何消息 这是客户端和服务器的完整代码 CLIENT public class Client extends Socket public Client String hostName int port throws Un
  • 如何在 PuTTY 中保存并运行 Java 文件?

    我是 AWS 亚马逊网络服务 的新手 所以这可能是一个基本问题 我在 AWS 上创建了一个 EC2 实例 我有一台 Windows 计算机 因此我使用 PUTTY 来连接 Linux 实例 连接到我的 EC2 实例后 我使用以下命令编写 J
  • SwingUtilities.invokeLater

    我的问题与SwingUtilities invokeLater 我应该什么时候使用它 每次需要更新 GUI 组件时都必须使用吗 它到底有什么作用 是否有替代方案 因为它听起来不直观并且添加了看似不必要的代码 Do I have to use
  • 在实现接口的类上强制使用单例模式

    我最好用一个例子来解释这个问题 我有一个接口模型可用于访问数据 模型可以有不同的实现 可以以各种格式表示数据 例如 XMl txt 格式等 Model不关心格式 可以说这样的一个实现是myxml模型 现在我想强迫myxml模型以及其他所有实
  • Java MYSQL/JDBC 查询从缓存的连接返回过时的数据

    我一直在 Stackoverflow 中寻找答案 但似乎找不到不涉及 Hibernate 或其他数据库包装器的答案 我直接通过 Tomcat 6 Java EE 应用程序中的 MYSQL 5 18 JDBC 驱动程序使用 JDBC 我正在缓
  • 有没有办法删除 JShell 中的导入?

    我正在发现 JShell 并且发现默认添加的导入 jshell gt imports import java io import java math import java net import java nio file import j
  • Java 9:AES-GCM 性能

    我进行了一个简单的测试来测量AES GCM https en wikipedia org wiki Galois Counter Mode表现在Java 9 通过在循环中加密字节缓冲区 结果有些令人困惑 本机 硬件 加速似乎有效 但并非总是
  • Java 执行器和长寿命线程

    我继承了一些使用 Executors newFixedThreadPool 4 的代码运行 4 个长寿命线程来完成应用程序的所有工作 这是推荐的吗 我读过Java 并发实践 https rads stackoverflow com amzn
  • 可空日期列合并问题

    我在 Geronimo 应用程序服务器上使用 JPA 和下面的 openjpa 实现 我也在使用MySQL数据库 我在更新具有可为空 Date 属性的对象时遇到问题 当我尝试合并 Date 属性设置为 null 的实体时 不会生成 sql
  • “mvn”不被识别为内部或外部命令、可操作程序或批处理文件

    可能是之前问过问题 但我发现了非常奇怪的错误 当我跑步时mvn versionbin 中的命令给出了版本和其他信息 但是 当我跑到垃圾箱外面时 它会出现异常 下面提到的结果 C Program Files apache maven 3 0
  • 在edittext android中插入imageview

    我想将 imageview 放在 edittext 中 可能吗 我检查了 evernote 应用程序 它能够将照片放在编辑文本部分 我想让我的应用程序完全相同 我如何才能将从图库中选择的图像视图放入编辑文本中 我首先尝试将 imagevie
  • 在 Spark MLlib 上使用 Java 中的 Breeze

    在尝试从Java使用MLlib时 使用微风矩阵运算的正确方法是什么 例如scala 中的乘法很简单 matrix vector 相应的功能在Java中是如何表达的 有一些方法 例如 colon times 可以通过正确的方式调用 breez
  • ImageIO.read(...) - 非常慢,有更好的方法吗?

    我正在加载大量将在我的应用程序中使用的图标 我计划在服务器启动时从 jar 中加载所有这些 然而 由于数百张图像加起来刚刚超过 9MB 执行此任务仍然需要 30 秒多的时间 我现在正在一个单独的线程中执行此操作 但这让我想知道我是否在代码中

随机推荐

  • 多视图综述以及图像检索

    1 1 算法分类 1 1 1 协同训练 该方法旨在最大限度地扩展所有观点的相互协议 并达成最广泛的共识 协同训练算法一般过程如图1所示 根据该过程对算法进行交替训练 利用先验信息或相互学习知识 使两种不同视图的一致性最大化 Co train
  • 秦九韶算法详解

    秦九韶算法 秦九韶算法是将一元n次多项式的求值问题转化为n个一次式的算法 比普通计算方式提高了一个数量级 普通算式 a x i 因为多次求幂 消耗了大量的计算时间 我们来分析一下秦九韶算法 例如 求 1 x 2x 2 3x 3 当x 2时的
  • MongoDB 数据库(一):MongoDB的介绍与安装

    目录 一 MongoDB数据库的介绍与安装 1 1 NoSQL数据库简介 1 2 MongoDB 简介 1 2 1 再议业务应用场景 1 2 2 为什么要使用 MongoDB 1 2 3 适用场景 二 安装和使用MongoDB客户端 2 1
  • C++新特性34_递归互斥量recursive_mutex与超时互斥量timed_mutex的使用(递归互斥量解决同一线程重复使用互斥量的需求;超时互斥量设置等待超时机制;解决互斥量阻塞问题)

    接上篇C 新特性33 死锁产生的原因及避免 线程在等待一个永远都不能成功的条件成立 从而进入到陷入休眠 永远不能被唤醒的状态 通过调整锁的使用顺序解决死锁问题 本篇将会学习互斥体的相关知识 C 新特性34 递归互斥量recursive mu
  • 测试开发面试题总结

    测试开发面试题 1 通过列表推导式完成下面数据类型转换 将 a 11 b 2 11 22 33 44 转换为以下格式 li1 a 11 b 2 11 22 33 44 2 Names python java php c c django u
  • 光控照明灯自动开关

    该光控照明灯自动开关电路采用继电器控制方式 可用来控制普通灯泡 日光灯 节能灯等多种照明灯具 可广泛用于车站 码头 机场等夜间需要连续照明的场所 电路结构与特点 如图所示光控照明灯自动开关电路 不仅具有结构简单 稳定可靠和安装方便等优点 而
  • LSTM这一篇就够了

    转自AI大本营https blog csdn net dQCFKyQDXYm3F8rB0 article details 82922386 短时记忆 NN 会受到短时记忆的影响 如果一条序列足够长 那它们将很难将信息从较早的时间步传送到后面
  • (2)Qt中的字符串类型

    字节数组 QByteArray 在Qt中QByteArray可以看做是C语言中 char 的升级版本 我们在使用这种类型的时候可通过这个类的构造函数申请一块动态内存 用于存储我们需要处理的字符串数据 1 构造函数 构造空对象 QByteAr
  • 记录一次合并单元格表格渲染错位问题。

    renderData this mergeSpanArr 系统名称合并的数组 this mergeSpanArrIndex 0 this zuhuSpanArr 租户合并列表 this zuhuSpanArrIndex 0 租户合并索引 l
  • 电脑怎么开启vt_华擎开启VT的方法

    第一步 重启电脑 屏幕亮起后不断按下 F2 键 进入BIOS页面 开机速度太快无法进入BIOS怎么办 第二步 在菜单中找到VT选项并开启 不同型号的主板 BIOS界面不相同 VT的叫法也不相同 1 进入BIOS页面后 找到 Advanced
  • 驾驭AI绘画:《AI魔法绘画》带你秒变顶级画手!

    同学们 抖音买家秀中的那些极具设计感的作品是怎么来的 你还在羡慕别人的绘画天赋 对着空白的画纸发呆吗 有没有想过将生硬的代码和灵动的艺术完美融合 有没有感到现代技术带来了戏剧性改变 从替代马车的汽车 到取代传统影像的数字摄影 再到今天的AI
  • Spring Expression Language(SpEL)实现ABAC鉴权模型, 动态计算实体的属性、操作类型、相关的环境来控制是否有对操作对象的权限

    author changjin wei 魏昌进 since 2022 11 26 ABAC授权模型 常用的授权模型 ABAC的访问控制 表达式语言 SpEL性能 ABAC实践 数据库设计 java程序 crud代码 security上下文
  • 使用jackson实现对象json相互转换(spring boot)

    之前的json转对象 对象转json 总是比较繁琐 不够简洁 自从接触到jackson之后 发现原来对象和json转换可以这么简单 拿一个天气预报的小例子来说明一下 如下图 若是有小误 还望指正 不说 直接上码 首先 在pom xml里弄好
  • 图像分辨率测试ISO12233 - 2017中文翻译

    译者序 目前的摄像头分辨率的测试 大多遵循ISO 12233标准 最近下载一份英文版的文档 和大家一起分享 仅供学习使用 目录 ISO 12233 Third Edition 2017 01 Foreword 前言 Introduction
  • Ant Design pro入门

    Ant Design pro入门 前言 一 了解Ant Design pro 二 使用步骤 1 快速入门 2 ant pro菜单 路由 前言 读此文章需要优先掌握知识 1 React 2 ts 3 Ant Design 一 了解Ant De
  • NLP学习(一)基础篇

    一 前言 2016年3月9日至15日和2017年5月23日至27日 分别在韩国首尔和中国嘉兴乌镇 韩国围棋九段棋手李世石 中国围棋九段棋手柯洁与人工智能围棋程序 阿尔法围棋 AlphaGo 之间的两场比赛 人类均以失败告终 更是激起了各种
  • 深度学习课程设计

    1 安装TensorFlow windows 命令窗口 pip install tensorflow 我之前已经安装过python 可能是因为安装python也安装了pip所以可以直接使用pip命令 之前下载过pycharm 但是没有激活
  • Ubuntu系统下pycharm导入numpy、sklearn等各类包的方法

    本方法适用于无法导入numpy pandas matplotlib sklearn等包 1 打开pycharm 点击左上角file gt setting gt Project gt Python Interpreter 2 点击 号后显示下
  • win10环境变量path误删(windows找不到文件%windir%\systempropertiesadvanced.exe)的解决办法

    首先给出错误 windows找不到文件 windir systempropertiesadvanced exe请确定文件是否正确后 再试一次 当时看到这个错误我真是绝望了 因为我各种百度找path变量怎么恢复 结果百度给一堆环境变量的设置方
  • java实现:《操作系统实验三》模拟内存管理

    固定分区分配 固定分区分配是最简单的一种多道程序存储管理方式 它将用户内存空间划分为若干个固定大小的区域 每个分区只装入一道作业 当有空闲分区时 便可以再从外存的后背作业队列中 选择适当大小的作业装入该分区 如此循环 优缺点 分区大小相等