备个份
动态分区管理:
Course:
public class Course { //进程类
private String desc; //进程描述
private int spaces; //进程所需内存大小
private Space matchspace; //进程运行时所占的内存分区
public Course(){}
public Course(int spaces,String desc){
this.spaces=spaces;
this.desc=desc;
matchspace=null;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public int getSpaces() {
return spaces;
}
public void setSpaces(int spaces) {
this.spaces = spaces;
}
public Space getMatchspace() {
return matchspace;
}
public void setMatchspace(Space matchspace) {
this.matchspace = matchspace;
}
public int compareTo(Course b){
return Integer.compare(this.spaces,b.spaces);
}
}
Space:
public class Space { //内存分区类
private int size; //内存分区大小
private int headAddr; //内存分区首地址
private Status status; //内存分区状态
public Space(){}
public Space(int size,int headAddr){
this.size=size;
this.headAddr=headAddr;
this.status=Status.FREE;
}
public Space(int size,int headAddr,Status status){
this.size=size;
this.headAddr=headAddr;
this.status=status;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getHeadAddr() {
return headAddr;
}
public void setHeadAddr(int headAddr) {
this.headAddr = headAddr;
}
public int compareTo(Space b,Methods x){ //空闲分区比较器
if(x==Methods.BEST) { //最佳适应法,比较内存分区大小,由小到大
return Integer.compare(this.size,b.size);
}
else if(x==Methods.FIRST){ //最先适应法,比较内存分区首地址,由小到大
return Integer.compare(this.headAddr,b.headAddr);
}
else{ //最坏适应法,比较内存分区大小,由大到小
return -(Integer.compare(this.size,b.size));
}
}
}
Methods / Status:
enum Methods { //内存算法
FIRST("最先适应法"),
BEST("最佳适应法"),
WORST("最坏适应法");
private final String desc;
private Methods(String desc){
this.desc=desc;
}
}
enum Status{ //内存分区使用状态
FREE("空闲分区"),
USING("已使用分区"),
EMPTY("空表目");
private final String desc;
private Status(String desc){
this.desc=desc;
}
}
Main:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
public static Main test=new Main();
public static Scanner scan=new Scanner(System.in);
public static LinkedList<Space> spaceList=new LinkedList<>(); //保存内存分区信息
public static ArrayList<Course> courseList=new ArrayList<>(); //保存已添加未分配的进程信息
public static ArrayList<Course> usingList=new ArrayList<>(); //保存已分配未回收的进程信息
public static int ROM;
public static Methods METHOD;
public void switchROM(){
System.out.println("-----修改内存大小-----");
System.out.print("新的内存大小为(会清空当前所有已分配进程):");
ROM=scan.nextInt();
spaceList.clear();
spaceList.add(new Space(ROM,0,Status.FREE));
for(Course a:usingList){
a.setMatchspace(null);
courseList.add(a);
}
usingList.clear();
}
public void switchMETHOD() {
System.out.println("-----修改分配算法-----");
System.out.println("1:最先适应法(按首地址从小到大排序)");
System.out.println("2:最佳适应法(按分区空间从小到大排序)");
System.out.println("3:最坏适应法(按分区空间从大到小排序)");
System.out.println("0:取消");
System.out.print("新的分配算法为:");
switch (scan.nextInt()) {
case 1 -> {
METHOD = Methods.FIRST;
break;
}
case 2 -> {
METHOD = Methods.BEST;
break;
}
case 3 -> {
METHOD = Methods.WORST;
break;
}
case 0->{
return;
}
}
}
public void addCOURSE(){
int addROM=0;
String addDesc="";
System.out.println("-----添加进程-----");
System.out.print("添加进程的数量为:");
int addNum=scan.nextInt();
int stepNum=0;
while(++stepNum<=addNum){
System.out.print("("+stepNum+"/"+addNum+") 占用空间(-1退出):");
addROM=scan.nextInt();
if(addROM==-1){
return;
}
System.out.print("("+stepNum+"/"+addNum+") 进程描述(-1退出):");
addDesc=scan.next();
if(addDesc.equals("-1")){
return;
}
courseList.add(new Course(addROM,addDesc));
}
}
public void selectrunCOURSE(){
System.out.println("-----分配进程-----");
if(courseList.size()==0){
System.out.println("尚未添加进程,分配失败");
return;
}
courseList.sort(Course::compareTo);
System.out.println("已添加的进程如下:");
int courseNum=1;
System.out.println("编号:\t占用空间:\t进程描述:");
for (Course iter : courseList) {
System.out.println(courseNum+"\t\t"+iter.getSpaces()+"\t\t\t"+iter.getDesc());
courseNum++;
}
int courseSign=-1;
while(courseSign<=0||courseSign>courseList.size()){
System.out.print("选择要分配的进程编号(-1退出):");
courseSign=scan.nextInt();
if(courseSign==-1){
return;
}
}
runCOURSE(courseList.get(courseSign-1));
}
public void selectrestoreCOURSE(){
System.out.println("-----回收进程-----");
if(usingList.size()==0){
System.out.println("尚未分配进程,回收失败");
return;
}
System.out.println("已分配的进程如下");
int courseNum=1;
System.out.println("编号:\t进程描述:\t内存首地址:\t占用空间:");
usingList.sort(Comparator.comparingInt(a -> a.getMatchspace().getHeadAddr()));
for(Course iter:usingList){
System.out.println(courseNum+"\t\t"+iter.getDesc()+"\t\t"+iter.getMatchspace().getHeadAddr()+"\t\t\t"+iter.getSpaces());
courseNum++;
}
int courseSign=-1;
while(courseSign<=0||courseSign>usingList.size()){
System.out.print("选择要回收的进程编号(-1退出):");
courseSign=scan.nextInt();
if(courseSign==-1){
return;
}
}
restoreCOURSE(usingList.get(courseSign-1));
}
public void runCOURSE(Course x){
if(spaceList.size()>1){
spaceList.sort((a,b)->a.compareTo(b,METHOD));
}
for(Space iter:spaceList){
if(iter.getStatus()==Status.FREE){ //要求分区尚未被分配给进程
if(iter.getSize()==x.getSpaces()){ //存在与进程所占空间相同的分区
x.setMatchspace(iter); //分配该分区给进程
usingList.add(x); //进程添加进已分配集合,从未分配集合中删除
courseList.remove(x);
spaceList.get(spaceList.indexOf(iter)).setStatus(Status.USING); //改变该分区状态为已使用
System.out.println("分配成功 首地址:"+spaceList.get(spaceList.indexOf(iter)).getHeadAddr()+" 占用空间:"+spaceList.get(spaceList.indexOf(iter)).getSize());
return;
}
else if(iter.getSize()>x.getSpaces()){ //存在比进程所占空间更大的分区
//分为两个分区,上分区分配给进程(状态为已使用),下分区作为空闲分区
Space newspaceA=new Space(x.getSpaces(),iter.getHeadAddr(),Status.USING);
Space newspaceB=new Space(iter.getSize()-x.getSpaces(),iter.getHeadAddr()+x.getSpaces());
x.setMatchspace(newspaceA); //分配上分区给进程
usingList.add(x); //程添加进已分配集合,从未分配集合中删除
courseList.remove(x);
spaceList.remove(iter); //由于空闲分区被切割,删除原有分区,加入被分割的两个分区
spaceList.add(newspaceA);
spaceList.add(newspaceB);
System.out.println("分配成功 首地址:"+newspaceA.getHeadAddr()+" 占用空间:"+newspaceA.getSize());
return;
}
}
}
System.out.println("分配失败,请检查剩余内存大小");
}
public void restoreCOURSE(Course x){
spaceList.sort((a,b)->a.compareTo(b, Methods.FIRST));
int waitsign=spaceList.indexOf(x.getMatchspace()); //回收内存分区在链表中的所在位置
x.setMatchspace(null); //将内存分区与进程分离
usingList.remove(x); //进程回收,从已分配集合中删除,添加进未分配集合
courseList.add(x);
//第一种情况:
// 不是首项&&不是最末项
// 上下均有相邻的空闲分区
if(waitsign!=(spaceList.size()-1)&&waitsign!=0&&spaceList.get(waitsign+1).getStatus()==Status.FREE&&spaceList.get(waitsign-1).getStatus()==Status.FREE){
//改变上相邻分区的信息,作为合并后的大分区,删除余下的表项
//此处将回收分区作为隐藏的表项存储在集合中,因此也要做删除操作,余下同理
spaceList.get(waitsign-1).setSize(spaceList.get(waitsign-1).getSize()+spaceList.get(waitsign+1).getSize()+spaceList.get(waitsign).getSize());
spaceList.remove(waitsign);
spaceList.remove(waitsign);
}
//第二种情况:
// 不是最末项
// 只有下相邻的空闲分区
else if(waitsign!=(spaceList.size()-1)&&spaceList.get(waitsign+1).getStatus()==Status.FREE){
//改变下相邻分区信息(大小、首地址),删除余下的表项
spaceList.get(waitsign).setSize(spaceList.get(waitsign).getSize()+spaceList.get(waitsign+1).getSize());
spaceList.remove(waitsign+1);
spaceList.get(waitsign).setStatus(Status.FREE);
}
//第三种情况:
// 不是首项
// 只有上相邻的空闲分区
else if(waitsign!=0&&spaceList.get(waitsign-1).getStatus()==Status.FREE){
//改变上相邻分区信息(大小),删除余下的表项
spaceList.get(waitsign-1).setSize(spaceList.get(waitsign-1).getSize()+spaceList.get(waitsign).getSize());
spaceList.remove(waitsign);
}
//第四种情况:
// 没有相邻的空闲分区
else{
//建立新表项(更改自己分区的状态即可)
spaceList.get(waitsign).setStatus(Status.FREE);
}
//打印回收成功信息
}
public void seeROM(){
System.out.println("-----查看内存分配情况-----");
System.out.println("当前的内存空间容量为:"+ROM);
System.out.println("正在占用内存空间的进程:");
System.out.println("进程描述:\t内存首地址:\t占用空间:");
usingList.sort(Comparator.comparingInt(a -> a.getMatchspace().getHeadAddr()));
for(Course iter:usingList){
System.out.println(iter.getDesc()+"\t\t"+iter.getMatchspace().getHeadAddr()+"\t\t\t"+iter.getSpaces());
}
System.out.println("空闲的内存空间:");
System.out.println("内存首地址:\t空间大小:");
spaceList.sort((a,b)->a.compareTo(b, Methods.FIRST));
for(Space iter:spaceList){
if(iter.getStatus()==Status.FREE){
System.out.println(iter.getHeadAddr()+"\t\t\t"+iter.getSize());
}
}
}
public static void main(String[] args) {
System.out.println("-----动态分区管理初始化-----");
test.switchROM();
test.switchMETHOD();
while(true){
System.out.println("-----动态分区管理主菜单-----");
System.out.println("1:修改内存大小(会清空当前所有已分配进程)");
System.out.println("2:修改分配算法");
System.out.println("3:添加进程");
System.out.println("4:分配进程(需要先添加进程)");
System.out.println("5:回收进程(需要先分配进程)");
System.out.println("6:查看内存分配情况");
System.out.println("7:还原初始状态");
System.out.println("0:退出");
System.out.print("选择功能编号:");
switch(scan.nextInt()){
case 1->{
test.switchROM();
break;
}
case 2->{
test.switchMETHOD();
break;
}
case 3->{
test.addCOURSE();
break;
}
case 4->{
test.selectrunCOURSE();
break;
}
case 5->{
test.selectrestoreCOURSE();
break;
}
case 6->{
test.seeROM();
break;
}
case 7->{
spaceList.clear();
courseList.clear();
usingList.clear();
spaceList.add(new Space(ROM,0,Status.FREE));
System.out.println("-----还原成功-----");
break;
}
case 0->{
return;
}
}
}
}
}
磁盘调度:
Loca:
public class Loca { //特殊序列类
private int position; //请求序列元素位置
private int front; //在当前磁头的移动方向之前还是之后
public Loca(){}
public Loca(int position){
this.position=position;
}
public Loca(int position,int front){
this.position=position;
this.front=front;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public int getFront() {
return front;
}
public void setFront(int front) {
this.front = front;
}
public int compareTo(Loca b,int POSITION){ //比较器
if(this.front!=b.front){ //如果方向不同,与磁头移动方向相同的排在前面
return -Integer.compare(this.front,b.front);
}
//如果方向相同,与磁头距离更短的排在前面
return Integer.compare(Math.abs(this.position-POSITION),Math.abs(b.position-POSITION));
}
}
Direction:
enum Direction {
BEHIND("沿磁道号减小的方向移动"),
FRONT("沿磁道号增加的方向移动");
private final String desc;
private Direction(String desc){
this.desc=desc;
}
}
Main:
import java.security.Signature;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
public static Scanner scan=new Scanner(System.in);
public static int ORIGINP; //初始磁头位置(只有重新设置才能改变)
public static int POSITION; //当前磁头位置(随序列运行而改变)
public static Direction DIRECTION; //磁头移动方向
public static ArrayList<Integer> SignList=new ArrayList<>(); //保存请求序列
public static Main test=new Main();
public void SetPOSITION(){
System.out.println("-----设置磁头位置-----");
System.out.print("请输入新的磁头位置:");
ORIGINP=scan.nextInt();
POSITION=ORIGINP;
}
public void SetArray(){
System.out.println("-----增加磁道访问请求序列-----");
System.out.print("输入序列(以空格分割,-1结束):");
int set=0,time=0;
while(true){
set=scan.nextInt();
if(set!=-1){
SignList.add(set);
}
else{
break;
}
time++;
}
if(time>0){
test.PrintArray();
}
}
public void PrintArray(){
System.out.println("当前的请求序列为:");
for(int i=0;i<SignList.size();++i){
System.out.print(i+1+"\t");
}
System.out.println();
for(int i=0;i<SignList.size();++i){
System.out.print(SignList.get(i)+"\t");
}
System.out.println();
}
public void DeleteArray(){
System.out.println("-----修改磁道访问请求序列-----");
if(SignList.size()==0){
System.out.println("修改失败,请先添加访问请求序列");
return;
}
test.PrintArray();
int sign=0,set=0;
System.out.print("输入要修改的编号(-1退出):");
sign=scan.nextInt();
if(sign==-1){
return;
}
System.out.print("输入要修改的值(-1删除):");
set=scan.nextInt();
if(set==-1){
SignList.remove(sign-1);
}
else{
SignList.set(sign-1,set);
}
}
public void RemoveArray(){
System.out.println("-----清空序列-----");
System.out.println("正在清空序列...");
SignList.clear();
System.out.println("正在还原磁头位置...");
POSITION=ORIGINP;
}
public void StartTesting(){
System.out.println("-----开始模拟调度-----");
if(SignList.size()==0){
System.out.println("调度失败,请先添加访问请求序列");
return;
}
test.PrintArray();
System.out.print("选择调度算法(1:FCFS,2:SSTF,3:SCAN,-1退出):");
switch(scan.nextInt()){
case 1->{
test.FCFSme();
POSITION=ORIGINP;
break;
}
case 2->{
test.SSTFme();
POSITION=ORIGINP;
break;
}
case 3->{
System.out.print("请输入磁头初始移动方向(1:沿磁道号增大 2:沿磁道号减小):");
switch(scan.nextInt()){
case 1->{
DIRECTION=Direction.FRONT;
break;
}
case 2->{
DIRECTION=Direction.BEHIND;
}
}
test.SCANme();
POSITION=ORIGINP;
break;
}
case -1->{
return;
}
}
}
public void FCFSme(){
System.out.println("---开始调度(FCFS先来先服务算法)---");
float Movement=0; //磁头总移动
for(int i=0;i<SignList.size();++i){ //共循环N次
int set=SignList.get(i);
System.out.print("第"+(i+1)+"次 原磁头:"+POSITION
+"\t下一个:"+set
+"\t移动数:"+Math.abs(POSITION-set)); //移动数取绝对值
Movement+=Math.abs(POSITION-set);
POSITION=set; //设置移动后的新磁头位置
System.out.println();
}
System.out.println("总寻道长度:"+Movement+"\n平均寻道长度:"+Movement/SignList.size());
System.out.println("-----调度完成-----");
}
public void SSTFme(){ //主方法
System.out.println("---开始调度(SSTF最短寻道时间算法)---");
float Movement=0; //磁头总移动
//由于磁头位置会变,要对元素作删除操作,这里作复制操作,以便不影响原序列
ArrayList<Integer> SSTFArray = new ArrayList<>(SignList);
for(int i=0;i<SignList.size();++i) {
SSTFArray.sort(this::SSTFcp); //按距离当前磁头位置的绝对值排序
int set=SSTFArray.get(0); //同样取第0个,也就是经排序后的最小元素
System.out.print("第"+(i+1)+"次 原磁头:"+POSITION
+"\t下一个:"+set
+"\t移动数:"+Math.abs(set-POSITION)); //移动数取绝对值
Movement+=Math.abs(set-POSITION);
POSITION=set; //设置移动后的新磁头位置
SSTFArray.remove(0); //删除元素,使得排序后的0号元素始终是最佳的
System.out.println();
}
System.out.println("总寻道长度:"+Movement+"\n平均寻道长度:"+Movement/SignList.size());
System.out.println("-----调度完成-----");
}
public int SSTFcp(Integer a,Integer b){ //排序器
return Integer.compare(Math.abs(a-POSITION),Math.abs(b-POSITION)); //比较绝对值
}
public void SCANme(){
System.out.println("---开始调度(SCAN扫描算法/电梯算法)---");
float Movement=0; //磁头总移动
ArrayList<Loca> LocaList=new ArrayList<>();
for(int i=0;i<SignList.size();++i){
LocaList.add(new Loca(SignList.get(i))); //同SSTF算法,复制序列
}
for(int i=0;i<SignList.size();++i){
for(int j=0;j<LocaList.size();++j){
//复制过来的序列没有front属性,逐个与磁头位置比较并设置
//共有两种情况front属性=-1:①磁头增加方向,比磁头位置小
// ②磁头减少方向,比磁头位置大
if(LocaList.get(j).getPosition()<POSITION&&DIRECTION==Direction.FRONT){
LocaList.get(j).setFront(-1);
}
else if(LocaList.get(j).getPosition()>POSITION&&DIRECTION==Direction.BEHIND){
LocaList.get(j).setFront(-1);
}
else{
LocaList.get(j).setFront(1);
}
}
LocaList.sort((a,b)-> a.compareTo(b,POSITION)); //使用排序器对序列排序
int set=LocaList.get(0).getPosition(); //取0号元素(最佳)
System.out.print("第"+(i+1)+"次 原磁头:"+POSITION
+"\t下一个:"+set
+"\t移动数:"+Math.abs(set-POSITION)); //移动数采用绝对值
Movement+=Math.abs(set-POSITION);
//如果下一个最佳的与磁头方向相反,要改变磁头移动方向
if(set<POSITION&&DIRECTION==Direction.FRONT){
DIRECTION=Direction.BEHIND;
}
else if(set>POSITION&&DIRECTION==Direction.BEHIND){
DIRECTION=Direction.FRONT;
}
POSITION=set; //移动磁头位置`
LocaList.remove(0); //同SSTF算法,保证0号元素一定是当前的最佳元素
System.out.println();
}
System.out.println("总寻道长度:"+Movement+"\n平均寻道长度:"+Movement/SignList.size());
System.out.println("-----调度完成-----");
}
public static void main(String[] args) {
System.out.println("-----磁盘调度系统-----");
System.out.println("-----初始化-----");
test.SetPOSITION();
while(true){
System.out.println("-----磁盘调度系统-----");
System.out.println("1:设置磁头位置");
System.out.println("2:添加磁道访问请求序列");
System.out.println("3:修改磁道访问请求序列");
System.out.println("4:开始模拟调度");
System.out.println("5:清空序列");
System.out.println("0:退出");
System.out.print("输入功能序号:");
switch(scan.nextInt()){
case 1->{
test.SetPOSITION();
break;
}
case 2->{
test.SetArray();
break;
}
case 3->{
test.DeleteArray();
break;
}
case 4->{
test.StartTesting();
break;
}
case 5->{
test.RemoveArray();
break;
}
case 0->{
return;
}
}
}
}
}