备个份
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); } }
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)); } } }
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; } }
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; } } } } }
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)); } }
enum Direction { BEHIND("沿磁道号减小的方向移动"), FRONT("沿磁道号增加的方向移动"); private final String desc; private Direction(String desc){ this.desc=desc; } }
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; } } } } }