进程管理系统的设计与实现

要求:
(1)设计一个完整的进程调度系统,至少包含三种常用的算法(FCFS、SPF、静态优先权、响应比、时间片轮转),系统中至少包含5个进程,并且能够体现进程的动态申请;

(2)定义PCB;

(3)结果要能够显示出进程的调度序列及进入系统的时间、运行时间、完成时间、周转时间、带权周转时间、优先权等必要信息;

(4〉设计的输入数据要能体现算法的思想

本人使用Java语言编写,编写过程中在网络中查找大量资料。

本人是本篇代码的唯一作者。

本代码仅限参考学习,禁止抄袭!

各算法介绍:

先来先服务算法First Come First Service(FCFS):

FCFS的意思是先来先服务(First Come First Service)。
顾名思义就是按照进程被添加到等待队列的先后顺序来进行调用的。

短进程优先算法Short Process First(SPF):

SPF的意思是短进程优先(Short Process First),服务时间短的进程在就绪队列前面。

静态优先级调度算法Static Priority-scheduling algorithm(SPSA):

系统在调度进程时按优先级从高到低进行调度,在进程运行过程中优先级不再动态地改变。

高响应比优先调度算法Highest Response Ratio Next(HRRN):

响应比 =(等待时间+要求服务时间)/ 要求服务时间
为每一个作业引入一个动态优先级,即优先级是可以改变的。
它随等待时间延长而增加,这将使长作业的优先级在等待期间不断地增加,
等到足够的时间后,必然有机会获得处理机。

时间片轮转算法Round Robin(RR):

系统把所有就绪进程按先来先服务规则排成一个队列,就绪队列中的所有进程,
可以依次轮流获得一个时间片的处理时间,然后系统又回到队列的开始部分,如此不断循环。

代码部分:

Main:

package osProject.sjs;import java.io.*;
import java.util.*;public class Main
{static int num;//进程数目static PCB[] arr = new PCB[100];static PCB[] arrUse = new PCB[100];static Scanner sc = new Scanner(System.in);public static void main(String[] args){System.out.println("欢迎进入进程管理系统,请按照提示输入进程信息。");Main M = new Main();M.inputProcessInf(M);//输入进程,选择输入进程的方式M.displayProcessInf();//展示进程初始信息//进入菜单选择功能,可以使用多个算法调度进程while(true){//此while为了多次选择功能i,在选择退出功能时置flag=1,然后退出//本程序使用arrUse而保留arr原数据,为了每次进入不同算法时不存在其他算法的遗留结果数据M.copyArray();//将arr中的数据内容拷贝到arrUse中,令算法使用arrUse中未被赋值过的干净数据int flag = 0;//用来标记是否需要退出选择算法,置1则退出算法M.displayMenu();//展示系统菜单,每执行完一次功能i,再次选择功能时展示一次while(true){//为了防止输入i的错误导致无法选择功能,此while直到正确选择功能i时退出,每个if的最后都要有breaktry{//在try语句块中书写可能发生异常的代码(选择功能),增强程序健壮性int i = sc.nextInt();if(i == 1){//选择先来先服务算法FCFSexecuteFCFS();//执行FCFS算法break;}else if(i == 2){//选择短进程优先算法SPFexecuteSPF();//执行SPF算法break;}else if(i == 3){//选择静态优先级调度算法SPSAexecuteSPSA();//执行SPSA算法break;}else if(i == 4){//选择高响应比优先调度算法HRRNexecuteHRRN();//执行HRRN算法break;}else if(i == 5){//时间片轮转算法RRexecuteRR();//执行RR算法break;}else if(i == 6){//选择退出系统flag = 1;//flag置1,表示需要退出系统break;}else{//输入i不是要求的选项,提示重新选择System.out.println("输入有误,请重新输入:");//提示功能i选择的错误//输入错误时不需要break,需要重新输入}}catch(Exception e){System.out.println("您输入的不是数字,请重新输入!");sc = new Scanner(System.in);//这一句要加,否则会进入死循环}}if(flag == 1){//当flag置1时,退出系统break;}}sc.close();}private static void executeRR() {//执行RR算法RR rr = new RR(num, arrUse, sc);//RR算法需要输入时间片大小,所以需要传入Scanner对象rr.run(); System.out.println("请选择是否将本次算法执行结果存入文件?");System.out.println("1.是\t 2.否");while(true){//while死循环是为了防止输入错误时令用户再次输入,否则输入错误后就跳出了,没法选择存文件int x = sc.nextInt();if(x == 1 || x == 2)  {if(x == 1)  rr.writeFile();//将类数组写入文件break;//当选择完文件操作后应该退出本层while}else{System.out.println("输入有误,请重新输入:");//提示文件操作的选择错误sc = new Scanner(System.in);//未选择完文件操纵,不需要退出本层while}}}private static void executeHRRN() {//执行HRRN算法HRRN hrrn = new HRRN(num, arrUse);hrrn.run(); System.out.println("请选择是否将本次算法执行结果存入文件?");System.out.println("1.是\t 2.否");while(true){//while死循环是为了防止输入错误时令用户再次输入,否则输入错误后就跳出了,没法选择存文件int x = sc.nextInt();if(x == 1 || x == 2)  {if(x == 1)  hrrn.writeFile();//将类数组写入文件break;//当选择完文件操作后应该退出本层while}else{System.out.println("输入有误,请重新输入:");//提示文件操作的选择错误sc = new Scanner(System.in);//未选择完文件操纵,不需要退出本层while}}}private static void executeSPSA() {//执行SPSA算法SPSA spsa = new SPSA(num, arrUse, sc);//SPSA算法要另外输入优先级,需要Scanner变量(也有其他方法)spsa.run(); System.out.println("请选择是否将本次算法执行结果存入文件?");System.out.println("1.是\t 2.否");while(true){//while死循环是为了防止输入错误时令用户再次输入,否则输入错误后就跳出了,没法选择存文件int x = sc.nextInt();if(x == 1 || x == 2)  {if(x == 1)  spsa.writeFile();//将类数组写入文件break;//当选择完文件操作后应该退出本层while}else{System.out.println("输入有误,请重新输入:");//提示文件操作的选择错误sc = new Scanner(System.in);//未选择完文件操纵,不需要退出本层while}}}private static void executeSPF() {//执行SPF算法SPF spf = new SPF(num, arrUse);spf.run(); System.out.println("请选择是否将本次算法执行结果存入文件?");System.out.println("1.是\t 2.否");while(true){//while死循环是为了防止输入错误时令用户再次输入,否则输入错误后就跳出了,没法选择存文件int x = sc.nextInt();if(x == 1 || x == 2)  {if(x == 1)  spf.writeFile();//将类数组写入文件break;//当选择完文件操作后应该退出本层while}else{System.out.println("输入有误,请重新输入:");//提示文件操作的选择错误sc = new Scanner(System.in);//未选择完文件操纵,不需要退出本层while}}}private static void executeFCFS() {//执行FCFS算法FCFS fcfs = new FCFS(num, arrUse);fcfs.run();System.out.println("请选择是否将本次算法执行结果存入文件?");System.out.println("1.是\t 2.否");while(true){//此while为了防止输入错误时令用户再次输入,否则输入错误后就跳出了,//没法选择存文件,此while在选择文件操作完成后退出int x = sc.nextInt();if(x == 1 || x == 2)  {if(x == 1)  fcfs.writeFile();//将类数组写入文件break;//当选择完文件操作后应该退出本层while}else{System.out.println("输入有误,请重新输入:");sc = new Scanner(System.in);//未选择完文件操纵,不需要退出本层while}}}private void displayMenu(){System.out.println("功能菜单:");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("***********************************");System.out.println("请选择要执行的操作:");}private void copyArray() {//将arr中的数据内容拷贝到arrUse中,使用arrUse而保留arr中的原始数据//不能使用对象直接赋值,那样它们会引用同一块内容,两者会不独立for(int i = 0; i < num; i++){arrUse[i] = new PCB();arrUse[i].setId(arr[i].getId());arrUse[i].setName(arr[i].getName());arrUse[i].setArriveTime(arr[i].getArriveTime());arrUse[i].setServiceTime(arr[i].getServiceTime());arrUse[i].setVisited(0);}}private void displayProcessInf(){//展示进程未执行算法时的初始信息System.out.println("进程初始信息如下:");for(int i = 0; i < num; i++){//使用式样化输出函数printf()输出信息,使信息便于观看//左对齐加"-","8"指域宽为8,占8个字符字符串用"s",整型用"d",浮点类型用"f"System.out.printf("%-8s \t%-8s \t%-8s \t%-8s\n","进程id", "进程名", "到达时间", "服务时间");System.out.printf("%-8d \t%-8s \t%-8d \t%-8d\n",arr[i].getId(), arr[i].getName(), arr[i].getArriveTime(), arr[i].getServiceTime());}System.out.println();}private void fileReadProcess(){//从文件中读入进程信息File file = new File("processInf.dat");try{FileInputStream fin = new FileInputStream(file);ObjectInputStream in = new ObjectInputStream(fin);num = fin.read();for(int i = 0; i < num; i++){arr[i] = (PCB)in.readObject();}in.close();fin.close();}catch(Exception e){System.out.println("文件\"processInf.dat\"不存在!请重新选择:");return;//若文件不存在需要直接return,否则会输出下方“已读入完成”的语句}System.out.println("文件\"processInf.dat\"中的算法数据已读入完成。");System.out.println();}private void fileWriteProcess(){//将进程块信息写入文件中File file = new File("processInf.dat");try{FileOutputStream fout = new FileOutputStream(file);ObjectOutputStream out = new ObjectOutputStream(fout);fout.write(num);for(int i = 0; i < num; i++){out.writeObject(arr[i]);}out.close();fout.close();}catch(Exception e){e.printStackTrace();}System.out.println("本次算法执行结果已存入文件\"processInf.dat\"中。");System.out.println();}private void readProcess(){//从控制台手动输入进程信息while(true){try{//在try语句块中书写可能发生异常的代码,增强程序健壮性System.out.println("请输入进程数目(2-99):");num = sc.nextInt();if(num < 2 || num > 99){System.out.println("您输入的数字不在要求范围内,请重新输入!");}else{System.out.println("进程数目为:" + num);System.out.println("请按照提示输入进程相关信息。");for(int i = 0; i < num; i++){arr[i] = new PCB();arr[i].setId(i+1);System.out.println("第" + (i+1) + "个进程名:");arr[i].setName(sc.next());System.out.println("进程到达时间:");arr[i].setArriveTime(sc.nextInt());System.out.println("进程服务时间:");arr[i].setServiceTime(sc.nextInt());arr[i].setVisited(0);//置进程i未被执行过}break;//输入完毕,此处记得要break,否则会死循环}}catch(Exception e){System.out.println("您输入的不是数字,请重新输入!");sc = new Scanner(System.in);//这一句要加,否则会进入死循环}}System.out.println("进程信息输入完成!");}private void inputProcessInf(Main M) {//输入进程,选择输入进程的方式System.out.println("请选择输入进程方式:");System.out.println("1.手动输入\t 2.文件读入");while(true){//为了防止输入x的错误导致无法选择功能,此while直到正确选择功能x时退出,每个if的最后都要有breakint x = sc.nextInt();if(x == 1){M.readProcess();//从控制台读入用户输入的进程块信息,读入一次进程信息,可以使用多个算法计算System.out.println("是否需要将进程信息保存到文件中?");System.out.println("1.是\t 2.否");while(true){//此while为了防止输入错误时令用户再次输入int y = sc.nextInt();if(y == 1 || y == 2)  {if(y == 1)  M.fileWriteProcess();//将程序中的进程块信息写入文件中break;//当写入操作完成后,退出while循环}else{System.out.println("输入有误,请重新输入:");sc = new Scanner(System.in);//未正确选择操作,不需要退出本层while}}break;}else if(x == 2){M.fileReadProcess();//从文件读入进程块信息break;}else{System.out.println("输入有误,请重新输入:");sc = new Scanner(System.in);//else中不用break,因为没有正确选择功能,需要在while中再次输入}}}}

PCB(进程控制块):

package osProject.sjs;import java.io.*;public class PCB implements Serializable
{/*** */private static final long serialVersionUID = 1L;private int id;//进程idprivate String name;//进程名称private int arriveTime;//进程进入系统的时间(未开始服务),进程到达时间private int serviceTime;//进程服务时间,进程服务时间,需提前给出private int alreadyServiceTime;//已经服务的时间,进程执行时记录private int startTime;//进程服务开始时间private int endTime;//进程服务完成时间private int turnaroundTime;//周转时间,作业完成时间 - 作业到达时间private double turnaroundTimeWithRight;//带权周转时间,周转时间 /服务时间private int priority;//优先级private double responseRatio;//HRRN中的响应比private int visited;//是否被执行过,置0为未被执行过,置1为被执行过PCB(){}//构造函数public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getArriveTime() {return arriveTime;}public void setArriveTime(int arriveTime) {this.arriveTime = arriveTime;}public int getServiceTime() {return serviceTime;}public void setServiceTime(int serviceTime) {this.serviceTime = serviceTime;}public int getAlreadyServiceTime() {return alreadyServiceTime;}public void setAlreadyServiceTime(int alreadyServiceTime) {this.alreadyServiceTime = alreadyServiceTime;}public int getStartTime() {return startTime;}public void setStartTime(int startTime) {this.startTime = startTime;}public int getEndTime() {return endTime;}public void setEndTime(int endTime) {this.endTime = endTime;}public int getTurnaroundTime() {return turnaroundTime;}public void setTurnaroundTime(int turnaroundTime) {this.turnaroundTime = turnaroundTime;}public double getTurnaroundTimeWithRight() {return turnaroundTimeWithRight;}public void setTurnaroundTimeWithRight(double turnaroundTimeWithRight) {this.turnaroundTimeWithRight = turnaroundTimeWithRight;}public int getPriority() {return priority;}public void setPriority(int priority) {this.priority = priority;}public double getResponseRatio() {return responseRatio;}public void setResponseRatio(double responseRatio) {this.responseRatio = responseRatio;}public int getVisited() {return visited;}public void setVisited(int visited) {this.visited = visited;}}

FCFS(先来先服务算法First Come First Service):

package osProject.sjs;import java.io.*;
import java.text.DecimalFormat;
//先来先服务算法First Come First Service(FCFS)
public class FCFS
{int num = 0;//进程数目PCB[] arr = new PCB[100];int totalTurnaroundTime = 0;//周转总时间double averageTotalTurnaroundTime;//平均周转时间,周转总时间/进程个数double totalTurnaroundTimeWithRight = 0;//带权周转总时间double averageTurnaroundTimeWithRight;//平均带权周转时间,带权周转总时间/进程个数FCFS() {}FCFS(int num, PCB[] arr){this.num = num;this.arr = arr;}void run(){//*************************进入先来先服务算法(FCFS)*************************//
//      for(PCB i : arr)
//      {//用foreach会出现报错,不知道为什么,报错如下:
//      //Exception in thread "main" java.lang.NullPointerException
//      //后面不止发现这一个报错,使用foreach还会导致其他报错,
//      //比如foreach遍历完arr后返回Main时会导致进入catch
//          System.out.println(i.getArriveTime());
//      }//模拟一个系统时间,系统时间自动增加,当某进程的到达时间 等于 该时刻系统时间时,该进程进入等待队列int systemTime = 0;int i = 0;//正在运行的进程的下标,i的范围:i <= j//按照到达系统时间排序后,最后一个到达系统的进程的下标j,int j = -1;//下标从0到j的进程都在等待队列中,j的范围:0 <= j <= num-1,初始队列中无进程,则为-1int flag = 0;//用于判断系统现在是否被进程占用,flag=1时表示系统正在运行进程totalTurnaroundTime = 0;//初始化周转总时间totalTurnaroundTimeWithRight = 0;//初始化带权周转总时间
//      displayProcessInf();//算法开始执行,展示进程初始信息quickSortArriveTime(arr, 0, num-1);//进入算法后先按照进程到达时间进行升序排序//*************************系统开始运行,开始执行进程*************************//System.out.println("先来先服务算法(FCFS)开始运行");while(true){//模拟进程执行,从 系统时间为0开始 到 最后一个进程执行结束System.out.println("当前时间:" + systemTime);//判断是否有进程进入系统(进入系统后进入等待队列),当有进程到达系统时,记录该进程并输出提示信息while(j+1 < num && systemTime == arr[j+1].getArriveTime()){//当该系统时间有到达的进程时,输出并记录进程到达系统,该判断独立执行,与flag无关//可能有多个进程同时到达,所以用while多次判断j++;System.out.println("进程" + arr[j].getName() + "到达系统");}//根据系统中是否有进程在执行,进行不同操作if(flag == 1){//flag=1表示 当前有进程在执行,判断该进程是否还在执行if(arr[i].getAlreadyServiceTime() != arr[i].getServiceTime()){//如果进程i已经服务的时间 != 应该服务的时间,即进程正在执行,则输出"正在执行"System.out.println("进程" + arr[i].getName() + "正在执行");//已经服务的时间和系统时间同步,应该在该时刻过去时增加,系统时间在程序末尾更新arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间}else{//如果进程i已经服务的时间 = 应该服务的时间,即进程服务结束System.out.println("进程" + arr[i].getName() + "执行结束");arr[i].setEndTime(systemTime);//记录进程i结束服务时间//计算进程的周转时间、带权周转时间arr[i].setTurnaroundTime(arr[i].getEndTime() - arr[i].getArriveTime());arr[i].setTurnaroundTimeWithRight(arr[i].getTurnaroundTime() / (double)arr[i].getServiceTime());//记录周转总时间、带权周转总时间totalTurnaroundTime += arr[i].getTurnaroundTime();totalTurnaroundTimeWithRight += arr[i].getTurnaroundTimeWithRight();if(i+1 <= j)  i++;//执行完一个进程后,如果等待队列中还有进程,则i加1,准备执行下一个进程flag = 0;//进程执行完,flag置0,表明系统中无进程执行}}if(flag == 0)//此处不用else,因为上面flag=1时可能将flag置0,此flag=0和flag=1是可能都发生的{//flag=0表示 当前无进程在执行,如果等待队列中有进程,则执行一个进程if(arr[i].getVisited() == 0){//当 等待队列中还有进程 并且 当前没有进程未被执行过//由于到达时间在最上面j的部分筛选过了,所以此处只需要筛选是否被执行过System.out.println("进程" + arr[i].getName() + "开始执行");//已经服务的时间和系统时间同步,应该在该时刻过去时增加,系统时间在程序末尾更新arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间arr[i].setStartTime(systemTime);//记录进程i的开始服务时间arr[i].setVisited(1);//别忘记标记进程i被访问过,否则最后一个进程每次都会进入该if反复执行flag = 1;//标志当前有进程执行}}systemTime++;//系统时间在程序末尾自动增加,表示该时刻过去System.out.println("此时正在执行进程i:" + i);System.out.println("此时等待队列尾部的是进程j:" + j);System.out.println("此时flag:" + flag);if(i == num-1 && j == num-1 && flag == 0){//当j=num-1时说明全部进程都已经到达系统,//当i=num-1并且flag=0时,表示本该在执行第num-1个进程,但是现在没有进程在执行//说明第num-1个进程即最后一个进程也执行完了,可以退出算法了break;}try{Thread.sleep(1000);//模拟系统运行,制造一个时间停顿}catch(Exception e){e.printStackTrace();}System.out.println();}displayResult();//算法执行结束,展示结果System.out.println("FCFS算法执行完成!");System.out.println();}// private void displayProcessInf()
//  {
//      System.out.println("系统开始运行,初始信息如下:");
//      for(int i = 0; i < num; i++)
//      {
//          //使用式样化输出函数printf()输出信息,使信息便于观看
//          //左对齐加"-","8"指域宽为8,占8个字符字符串用"s",整型用"d",浮点类型用"f"
//          System.out.printf("%-8s \t%-8s \t%-8s \t%-8s\n",
//                  "进程id", "进程名", "到达时间", "服务时间");
//          System.out.printf("%-8d \t%-8s \t%-8d \t%-8d\n",
//                  arr[i].getId(), arr[i].getName(), arr[i].getArriveTime(), arr[i].getServiceTime());
//      }
//      System.out.println();
//  }private void displayResult(){//这个函数不方便写在Main里让每个算法用同一份函数,因为平均周转时间和平均带权周转时间两个变量是存在于算法的类中的,不在Main中System.out.println("系统运行结束,运行结果如下:");//使用式样化输出函数printf()输出信息,使信息便于观看System.out.printf("%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s\n","进程id", "进程名", "到达时间", "服务时间", "服务开始时间", "服务完成时间", "周转时间", "带权周转时间");for(int i = 0; i < num; i++){System.out.printf("%-8d \t%-8s \t%-8d \t%-8d \t%-8d \t%-8d \t%-8d \t%-8.2f\n",arr[i].getId(), arr[i].getName(), arr[i].getArriveTime(), arr[i].getServiceTime(),arr[i].getStartTime(), arr[i].getEndTime(), arr[i].getTurnaroundTime(), arr[i].getTurnaroundTimeWithRight());}averageTotalTurnaroundTime = totalTurnaroundTime / (double)num;averageTurnaroundTimeWithRight = totalTurnaroundTimeWithRight / (double)num;System.out.printf("平均周转时间:%.2f\n", averageTotalTurnaroundTime);System.out.printf("平均带权周转时间:%.2f\n", averageTurnaroundTimeWithRight);System.out.println();}void writeFile(){//将算法本次运行结果写入文件File file = new File("fcfsResult.txt");try{FileWriter fw = new FileWriter(file);fw.write("本次算法运行结果如下:\n");fw.write("进程id" + "\t进程名" + "\t到达时间" + "\t服务时间" + "\t服务开始时间" + "\t服务完成时间" + "\t周转时间" + "\t带权周转时间" + "\n");for(int i = 0; i < num; i++){fw.write(String.valueOf(arr[i].getId()) + "\t" + (arr[i].getName()) + "\t" + String.valueOf(arr[i].getArriveTime()) + "\t" + String.valueOf(arr[i].getServiceTime()) + "\t" + String.valueOf(arr[i].getStartTime()) + "\t\t" + String.valueOf(arr[i].getEndTime()) + "\t\t" + String.valueOf(arr[i].getTurnaroundTime()) + "\t" + new DecimalFormat("0.00").format(arr[i].getTurnaroundTimeWithRight()) + "\n");}//new DecimalFormat("0.00").format(averageTotalTurnaroundTime)  此代码是将double类型的变量格式化转换为字符串fw.write("平均周转时间:" + new DecimalFormat("0.00").format(averageTotalTurnaroundTime) + "\n");fw.write("平均带权周转时间:" + new DecimalFormat("0.00").format(averageTurnaroundTimeWithRight) + "\n");fw.close();}catch(Exception e){e.printStackTrace();}System.out.println("本次算法执行结果已存入文件\"fcfsResult.txt\"中。");System.out.println();}private void quickSortArriveTime(PCB[] arr, int l, int r){//将进程块按照 到达时间 从小到大升序排序int i = l;int j = r;PCB key = new PCB();key = arr[l];if(i >= j)  return;while(i < j){while(i < j && key.getArriveTime() <= arr[j].getArriveTime())j--;arr[i] = arr[j];while(i < j && key.getArriveTime() >= arr[i].getArriveTime())i++;arr[j] = arr[i];}arr[i] = key;quickSortArriveTime(arr, l, i-1);quickSortArriveTime(arr, i+1, r);}
}

SPSA(静态优先级调度算法Static Priority-scheduling algorithm):

package osProject.sjs;import java.io.*;
import java.text.DecimalFormat;
import java.util.Scanner;//静态优先级调度算法Static Priority-scheduling algorithm(SPSA)
public class SPSA
{int num = 0;//进程数目PCB[] arr = new PCB[100];int totalTurnaroundTime = 0;//周转总时间double averageTotalTurnaroundTime;//平均周转时间,周转总时间/进程个数double totalTurnaroundTimeWithRight = 0;//带权周转总时间double averageTurnaroundTimeWithRight;//平均带权周转时间,带权周转总时间/进程个数Scanner sc;SPSA() {}SPSA(int num, PCB[] arr, Scanner sc){this.num = num;this.arr = arr;this.sc = sc;}void run() {//*************************进入静态优先级调度算法(SPSA)*************************//readPriority();//读入各进程的优先级//模拟一个系统时间,系统时间自动增加,当某进程的到达时间 等于 该时刻系统时间时,该进程进入等待队列int systemTime = 0;int i = 0;//正在运行的进程的下标,i的范围:i <= j//按照到达系统时间排序后,最后一个到达系统的进程的下标j,int j = -1;//下标从0到j的进程都在等待队列中,j的范围:0 <= j <= num-1,初始队列中无进程,则为-1int flag = 0;//用于判断系统现在是否被进程占用,flag=1时表示系统正在运行进程totalTurnaroundTime = 0;//初始化周转总时间totalTurnaroundTimeWithRight = 0;//初始化带权周转总时间quickSortArriveTime(arr, 0, num-1);//进入算法后先按照进程到达时间进行升序排序//*************************系统开始运行,开始执行进程*************************//System.out.println("静态优先级调度算法(SPSA)开始运行");while(true){//模拟进程执行,从 系统时间为0开始 到 最后一个进程执行结束System.out.println("当前时间:" + systemTime);//判断是否有进程进入系统(进入系统后进入等待队列),当有进程到达系统时,记录该进程并输出提示信息while(j+1 < num && systemTime == arr[j+1].getArriveTime()){//当该系统时间有到达的进程时,输出并记录进程到达系统,该判断独立执行,与flag无关//可能有多个进程同时到达,所以用while多次判断j++;System.out.println("进程" + arr[j].getName() + "到达系统");}//根据系统中是否有进程在执行,进行不同操作if(flag == 1){//flag=1表示 当前有进程在执行,判断该进程是否还在执行if(arr[i].getAlreadyServiceTime() != arr[i].getServiceTime()){//如果进程i已经服务的时间 != 应该服务的时间,即进程正在执行,则输出"正在执行"System.out.println("进程" + arr[i].getName() + "正在执行");arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间}else{//如果进程i已经服务的时间 = 应该服务的时间,即进程服务结束System.out.println("进程" + arr[i].getName() + "执行结束");arr[i].setEndTime(systemTime);//记录进程i结束服务时间//计算进程的周转时间、带权周转时间arr[i].setTurnaroundTime(arr[i].getEndTime() - arr[i].getArriveTime());arr[i].setTurnaroundTimeWithRight(arr[i].getTurnaroundTime() / (double)arr[i].getServiceTime());//记录周转总时间、带权周转总时间totalTurnaroundTime += arr[i].getTurnaroundTime();totalTurnaroundTimeWithRight += arr[i].getTurnaroundTimeWithRight();//此处不要令i加1了,找下一个需要执行的进程的任务交给flag=0的语句块,FCFS算法可以直接i+1,其他算法不可以
//                  if(i+1 <= j)  i++;//执行完一个进程后,如果等待队列中还有进程,则i加1,准备执行下一个进程flag = 0;//进程执行完,flag置0,表明系统中无进程执行}}if(flag == 0)//此处不用else,因为上面flag=1时可能将flag置0,此flag=0和flag=1是可能都发生的{//flag=0表示 当前无进程在执行,如果等待队列中有进程,则执行一个进程//找到拥有最大优先级并且没有被执行的进程并执行它i = findMaxPriorityIndex(j);//把拥有最大优先级的进程下标赋值给i,然后执行if(arr[i].getVisited() == 0){//当 当前没有进程在执行 并且 进程i未被执行过  //此if判断是必要的,因为上方函数在找不到符合条件的进程时返回的i为num-1,//如果不执行if,则会反复执行进程num-1,导致算法陷入死循环System.out.println("进程" + arr[i].getName() + "开始执行");arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间arr[i].setStartTime(systemTime);//记录进程i的开始服务时间arr[i].setVisited(1);//别忘记标记进程i被访问过,否则最后一个进程每次都会进入该if反复执行flag = 1;//标志当前有进程执行}}systemTime++;//系统时间在程序末尾自动增加,表示该时刻过去System.out.println("此时正在执行进程i:" + i);System.out.println("此时等待队列尾部的是进程j:" + j);System.out.println("此时flag:" + flag);//SPF算法不能单纯的再用这个if判断是否退出算法了(不是按到达时间顺序选取进程执行的算法都不行)//因为SPF算法不是按照FCFS一样从下标为0的进程顺序执行到下标为num-1的进程//最后一个执行的进程的下标不一定是num-1,所以不能用i=num-1来判断是否全部进程都执行完毕//但是为了此处退出算法的判断所有算法都统一,本人改写了最后给下标i赋值的代码,//当全部进程都执行完毕时,令i = num-1//使得该判断方式仍然成立,所以仍然使用此判断方式if(i == num-1 && j == num-1 && flag == 0){//当j=num-1时说明全部进程都已经到达系统,//当i=num-1并且flag=0时,表示本该在执行第num-1个进程,但是现在没有进程在执行//说明第num-1个进程即最后一个进程也执行完了,可以退出算法了break;}try{Thread.sleep(1000);//模拟系统运行,制造一个时间停顿}catch(Exception e){e.printStackTrace();}System.out.println();}displayResult();//算法执行结束,展示结果System.out.println("SPSA算法执行完成!");System.out.println();}private int findMaxPriorityIndex(int j){//遍历此时到达系统的所有进程,找到拥有最大优先级的进程int maxPriority = -1;//记录最大的优先级,初值设为一个很小的值int maxPriorityIndex = num-1;//记录拥有最大优先级进程的下标,默认设为等待队列中最后一个进程的下标,//当未找到 拥有最大优先级并且未被访问过的变量 时,即所有进程都被执行过时,i被赋值为num-1,//使得下方判断是否退出算法时判断可以退出算法,否则会陷入 既没有进程在执行,又不退出算法 的状态。for(int k = 0; k <= j; k++){//此时等待队列中的进程下标从0到jif(arr[k].getVisited() == 0){//如果进程k未被执行过if(arr[k].getPriority() > maxPriority){//如果 进程k的最大优先级 大于 记录的最大优先级,则更新记录maxPriority = arr[k].getPriority();maxPriorityIndex = k;}else if(arr[k].getServiceTime() < arr[maxPriorityIndex].getServiceTime() && arr[k].getPriority() == maxPriority){//如果优先级相同,则选择服务时间少的进程maxPriority = arr[k].getPriority();maxPriorityIndex = k;}}}return maxPriorityIndex;}private void readPriority() {//读入各进程的优先级System.out.println("请按照提示输入各进程的优先级:");for(int i = 0; i < num; i++){System.out.println("进程" + arr[i].getName() + "的优先级:");arr[i].setPriority(sc.nextInt());}System.out.println("进程的优先级全部录入完成!");System.out.println();}private void displayResult(){//这个函数不方便写在Main里让每个算法用同一份函数,因为平均周转时间和平均带权周转时间两个变量是存在于算法的类中的,不在Main中System.out.println("系统运行结束,运行结果如下:");//使用式样化输出函数printf()输出信息,使信息便于观看System.out.printf("%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s\n","进程id", "进程名", "优先级", "到达时间", "服务时间", "服务开始时间", "服务完成时间", "周转时间", "带权周转时间");for(int i = 0; i < num; i++){System.out.printf("%-8d \t%-8s \t%-8d \t%-8d \t%-8d \t%-8d \t%-8d \t%-8d \t%-8.2f\n",arr[i].getId(), arr[i].getName(), arr[i].getPriority(), arr[i].getArriveTime(), arr[i].getServiceTime(),arr[i].getStartTime(), arr[i].getEndTime(), arr[i].getTurnaroundTime(), arr[i].getTurnaroundTimeWithRight());}averageTotalTurnaroundTime = totalTurnaroundTime / (double)num;averageTurnaroundTimeWithRight = totalTurnaroundTimeWithRight / (double)num;System.out.printf("平均周转时间:%.2f\n", averageTotalTurnaroundTime);System.out.printf("平均带权周转时间:%.2f\n", averageTurnaroundTimeWithRight);System.out.println();}void writeFile(){//将算法本次运行结果写入文件File file = new File("spsaResult.txt");try{FileWriter fw = new FileWriter(file);fw.write("本次算法运行结果如下:\n");fw.write("进程id" + "\t进程名" + "\t优先级" + "\t到达时间" + "\t服务时间" + "\t服务开始时间" + "\t服务完成时间" + "\t周转时间" + "\t带权周转时间" + "\n");for(int i = 0; i < num; i++){fw.write(String.valueOf(arr[i].getId()) + "\t" + (arr[i].getName()) + "\t" + String.valueOf(arr[i].getArriveTime()) + "\t" + String.valueOf(arr[i].getServiceTime()) + "\t" + String.valueOf(arr[i].getPriority()) +"\t" + String.valueOf(arr[i].getStartTime()) + "\t\t" + String.valueOf(arr[i].getEndTime()) + "\t\t" + String.valueOf(arr[i].getTurnaroundTime()) + "\t" + new DecimalFormat("0.00").format(arr[i].getTurnaroundTimeWithRight()) + "\n");}fw.write("平均周转时间:" + new DecimalFormat("0.00").format(averageTotalTurnaroundTime) + "\n");fw.write("平均带权周转时间:" + new DecimalFormat("0.00").format(averageTurnaroundTimeWithRight) + "\n");fw.close();}catch(Exception e){e.printStackTrace();}System.out.println("本次算法执行结果已存入文件\"spsaResult.txt\"中。");System.out.println();}private void quickSortArriveTime(PCB[] arr, int l, int r){//将进程块按照 到达时间 从小到大升序排序int i = l;int j = r;PCB key = new PCB();key = arr[l];if(i >= j)  return;while(i < j){while(i < j && key.getArriveTime() <= arr[j].getArriveTime())j--;arr[i] = arr[j];while(i < j && key.getArriveTime() >= arr[i].getArriveTime())i++;arr[j] = arr[i];}arr[i] = key;quickSortArriveTime(arr, l, i-1);quickSortArriveTime(arr, i+1, r);}}

SPF(短进程优先算法Short Process First):

package osProject.sjs;import java.io.*;
import java.text.DecimalFormat;//短进程优先算法Short Process First(SPF)
public class SPF
{int num = 0;//进程数目PCB[] arr = new PCB[100];int totalTurnaroundTime = 0;//周转总时间double averageTotalTurnaroundTime;//平均周转时间,周转总时间/进程个数double totalTurnaroundTimeWithRight = 0;//带权周转总时间double averageTurnaroundTimeWithRight;//平均带权周转时间,带权周转总时间/进程个数SPF() {}SPF(int num, PCB[] arr){this.num = num;this.arr = arr;}void run() {//*************************进入短进程优先算法(SPF)*************************////模拟一个系统时间,系统时间自动增加,当某进程的到达时间 等于 该时刻系统时间时,该进程进入等待队列int systemTime = 0;int i = 0;//正在运行的进程的下标,i的范围:i <= j//按照到达系统时间排序后,最后一个到达系统的进程的下标j,int j = -1;//下标从0到j的进程都在等待队列中,j的范围:0 <= j <= num-1,初始队列中无进程,则为-1int flag = 0;//用于判断系统现在是否被进程占用,flag=1时表示系统正在运行进程totalTurnaroundTime = 0;//初始化周转总时间totalTurnaroundTimeWithRight = 0;//初始化带权周转总时间quickSortArriveTime(arr, 0, num-1);//进入算法后先按照进程到达时间进行升序排序//*************************系统开始运行,开始执行进程*************************//System.out.println("短进程优先算法(SPF)开始运行");while(true){//模拟进程执行,从 系统时间为0开始 到 最后一个进程执行结束System.out.println("当前时间:" + systemTime);//当有进程到达系统时,记录该进程并输出提示信息//判断是否有进程进入系统(进入系统后进入等待队列),当有进程到达系统时,记录该进程并输出提示信息while(j+1 < num && systemTime == arr[j+1].getArriveTime()){//当该系统时间有到达的进程时,输出并记录进程到达系统,该判断独立执行,与flag无关//可能有多个进程同时到达,所以用while多次判断j++;System.out.println("进程" + arr[j].getName() + "到达系统");//短进程优先算法,每次有进程到达系统都要按照服务时间排序,将服务时间短的排在前面//等待队列中现在是下标从0到j-1的进程,队列都是已经到达的进程,所有只需要关注服务时间
//              quickSortServiceTime(arr, 0, j-1);//按照服务时间从小到大升序排序//经测试发现,此处不能将arr排序,否则下面arr[i]指向的内容会变,选最短服务时间进程在下面遍历选择}//根据系统中是否有进程在执行,进行不同操作if(flag == 1){//flag=1表示 当前有进程在执行,判断该进程是否还在执行if(arr[i].getAlreadyServiceTime() != arr[i].getServiceTime()){//如果进程i已经服务的时间 != 应该服务的时间,即进程正在执行,则输出"正在执行"System.out.println("进程" + arr[i].getName() + "正在执行");arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间}else{//如果进程i已经服务的时间 = 应该服务的时间,即进程服务结束System.out.println("进程" + arr[i].getName() + "执行结束");arr[i].setEndTime(systemTime);//记录进程i结束服务时间//计算进程的周转时间、带权周转时间arr[i].setTurnaroundTime(arr[i].getEndTime() - arr[i].getArriveTime());arr[i].setTurnaroundTimeWithRight(arr[i].getTurnaroundTime() / (double)arr[i].getServiceTime());//记录周转总时间、带权周转总时间totalTurnaroundTime += arr[i].getTurnaroundTime();totalTurnaroundTimeWithRight += arr[i].getTurnaroundTimeWithRight();//此处不要令i加1了,找下一个需要执行的进程的任务交给flag=0的语句块,FCFS算法可以直接i+1,其他算法不可以
//                  if(i+1 <= j)  i++;//执行完一个进程后,如果等待队列中还有进程,则i加1,准备执行下一个进程flag = 0;//进程执行完,flag置0,表明系统中无进程执行}}if(flag == 0)//此处不用else,因为上面flag=1时可能将flag置0,此flag=0和flag=1是可能都发生的{//flag=0表示 当前无进程在执行,如果等待队列中有进程,则执行一个进程//找到服务时间最小并且没有被执行的进程并执行它i = findMinServiceTimeIndex(j);//把拥有最小服务时间的进程下标赋值给i,然后执行if(arr[i].getVisited() == 0){//当 当前没有进程在执行 并且 进程i未被执行过,则执行进程i//此if判断是必要的,因为上方函数在找不到符合条件的进程时返回的i为num-1,//如果不执行if,则会反复执行进程num-1,导致算法陷入死循环System.out.println("进程" + arr[i].getName() + "开始执行");arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间arr[i].setStartTime(systemTime);//记录进程i的开始服务时间arr[i].setVisited(1);//别忘记标记进程i被访问过,否则最后一个进程每次都会进入该if反复执行flag = 1;//标志当前有进程执行}}systemTime++;//系统时间在程序末尾自动增加,表示该时刻过去System.out.println("此时正在执行进程i:" + i);System.out.println("此时等待队列尾部的是进程j:" + j);System.out.println("此时flag:" + flag);//SPF算法不能单纯的再用这个if判断是否退出算法了(不是按到达时间顺序选取进程执行的算法都不行)//因为SPF算法不是按照FCFS一样从下标为0的进程顺序执行到下标为num-1的进程//最后一个执行的进程的下标不一定是num-1,所以不能用i=num-1来判断是否全部进程都执行完毕//但是为了此处退出算法的判断所有算法都统一,本人改写了最后给下标i赋值的代码,//当全部进程都执行完毕时,令i = num-1//使得该判断方式仍然成立,所以仍然使用此判断方式if(i == num-1 && j == num-1 && flag == 0){//当j=num-1时说明全部进程都已经到达系统,//当i=num-1并且flag=0时,表示本该在执行第num-1个进程,但是现在没有进程在执行//说明第num-1个进程即最后一个进程也执行完了,可以退出算法了break;}try{Thread.sleep(1000);//模拟系统运行,制造一个时间停顿}catch(Exception e){e.printStackTrace();}System.out.println();}displayResult();//算法执行结束,展示结果System.out.println("SPF算法执行完成!");System.out.println();}private int findMinServiceTimeIndex(int j){//遍历此时到达系统的所有进程,找到拥有最小服务时间的进程int minServiceTime = 0x3f3f3f3f;//记录最小的服务时间,初值设为一个很大的值int minServiceTimeIndex = num-1;//记录拥有最小服务时间进程的下标,默认设为等待队列中最后一个进程的下标,//当未找到 拥有最小服务时间并且未被访问过的变量 时,即所有进程都被执行过时,i被赋值为num-1,//使得下方判断是否退出算法时判断可以退出算法,否则会陷入 既没有进程在执行,又不退出算法 的状态。for(int k = 0; k <= j; k++){//此时等待队列中的进程下标从0到jif(arr[k].getServiceTime() < minServiceTime && arr[k].getVisited() == 0){//如果进程k的服务时间小于记录的最小时间 并且 进程k未被执行过minServiceTime = arr[k].getServiceTime();minServiceTimeIndex = k;}}return minServiceTimeIndex;}private void displayResult(){//这个函数不方便写在Main里让每个算法用同一份函数,因为平均周转时间和平均带权周转时间两个变量是存在于算法的类中的,不在Main中System.out.println("系统运行结束,运行结果如下:");//使用式样化输出函数printf()输出信息,使信息便于观看System.out.printf("%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s\n","进程id", "进程名", "到达时间", "服务时间", "服务开始时间", "服务完成时间", "周转时间", "带权周转时间");for(int i = 0; i < num; i++){System.out.printf("%-8d \t%-8s \t%-8d \t%-8d \t%-8d \t%-8d \t%-8d \t%-8.2f\n",arr[i].getId(), arr[i].getName(), arr[i].getArriveTime(), arr[i].getServiceTime(),arr[i].getStartTime(), arr[i].getEndTime(), arr[i].getTurnaroundTime(), arr[i].getTurnaroundTimeWithRight());}averageTotalTurnaroundTime = totalTurnaroundTime / (double)num;averageTurnaroundTimeWithRight = totalTurnaroundTimeWithRight / (double)num;System.out.printf("平均周转时间:%.2f\n", averageTotalTurnaroundTime);System.out.printf("平均带权周转时间:%.2f\n", averageTurnaroundTimeWithRight);System.out.println();}void writeFile(){//将算法本次运行结果写入文件File file = new File("spfResult.txt");try{FileWriter fw = new FileWriter(file);fw.write("本次算法运行结果如下:\n");fw.write("进程id" + "\t进程名" + "\t到达时间" + "\t服务时间" + "\t服务开始时间" + "\t服务完成时间" + "\t周转时间" + "\t带权周转时间" + "\n");for(int i = 0; i < num; i++){fw.write(String.valueOf(arr[i].getId()) + "\t" + (arr[i].getName()) + "\t" + String.valueOf(arr[i].getArriveTime()) + "\t" + String.valueOf(arr[i].getServiceTime()) + "\t" + String.valueOf(arr[i].getStartTime()) + "\t\t" + String.valueOf(arr[i].getEndTime()) + "\t\t" + String.valueOf(arr[i].getTurnaroundTime()) + "\t" + new DecimalFormat("0.00").format(arr[i].getTurnaroundTimeWithRight()) + "\n");}fw.write("平均周转时间:" + new DecimalFormat("0.00").format(averageTotalTurnaroundTime) + "\n");fw.write("平均带权周转时间:" + new DecimalFormat("0.00").format(averageTurnaroundTimeWithRight) + "\n");fw.close();}catch(Exception e){e.printStackTrace();}System.out.println("本次算法执行结果已存入文件\"spfResult.txt\"中。");System.out.println();}private void quickSortArriveTime(PCB[] arr, int l, int r){//将进程块按照 到达时间 从小到大升序排序int i = l;int j = r;PCB key = new PCB();key = arr[l];if(i >= j)  return;while(i < j){while(i < j && key.getArriveTime() <= arr[j].getArriveTime())j--;arr[i] = arr[j];while(i < j && key.getArriveTime() >= arr[i].getArriveTime())i++;arr[j] = arr[i];}arr[i] = key;quickSortArriveTime(arr, l, i-1);quickSortArriveTime(arr, i+1, r);}//    private void quickSortServiceTime(PCB[] arr, int l, int r)
//  {//将进程块按照服务时间从小到大升序排序
//      int i = l;
//      int j = r;
//      PCB key = new PCB();
//      key = arr[l];
//      if(i >= j)  return;
//      while(i < j)
//      {
//          while(i < j && key.getServiceTime() <= arr[j].getServiceTime())
//              j--;
//          arr[i] = arr[j];
//          while(i < j && key.getServiceTime() >= arr[i].getServiceTime())
//              i++;
//          arr[j] = arr[i];
//      }
//      arr[i] = key;
//      quickSortServiceTime(arr, l, i-1);
//      quickSortServiceTime(arr, i+1, r);
//  }}

HRRN(高响应比优先调度算法Highest Response Ratio Next):

package osProject.sjs;import java.io.*;
import java.text.DecimalFormat;//高响应比优先调度算法Highest Response Ratio Next(HRRN)
//响应比 =(等待时间+要求服务时间)/ 要求服务时间    等待时间 = 当前系统时间 - 到达时间
public class HRRN
{int num = 0;//进程数目PCB[] arr = new PCB[100];int totalTurnaroundTime = 0;//周转总时间double averageTotalTurnaroundTime;//平均周转时间,周转总时间/进程个数double totalTurnaroundTimeWithRight = 0;//带权周转总时间double averageTurnaroundTimeWithRight;//平均带权周转时间,带权周转总时间/进程个数HRRN() {}HRRN(int num, PCB[] arr){this.num = num;this.arr = arr;}void run() {//*************************进入高响应比优先调度算法(HRRN)*************************////模拟一个系统时间,系统时间自动增加,当某进程的到达时间 等于 该时刻系统时间时,该进程进入等待队列int systemTime = 0;int i = 0;//正在运行的进程的下标,i的范围:i <= j//按照到达系统时间排序后,最后一个到达系统的进程的下标j,int j = -1;//下标从0到j的进程都在等待队列中,j的范围:0 <= j <= num-1,初始队列中无进程,则为-1int flag = 0;//用于判断系统现在是否被进程占用,flag=1时表示系统正在运行进程totalTurnaroundTime = 0;//初始化周转总时间totalTurnaroundTimeWithRight = 0;//初始化带权周转总时间quickSortArriveTime(arr, 0, num-1);//进入算法后先按照进程到达时间进行升序排序//*************************系统开始运行,开始执行进程*************************//System.out.println("高响应比优先调度算法(HRRN   )开始运行");while(true){//模拟进程执行,从 系统时间为0开始 到 最后一个进程执行结束System.out.println("当前时间:" + systemTime);//判断是否有进程进入系统(进入系统后进入等待队列),当有进程到达系统时,记录该进程并输出提示信息while(j+1 < num && systemTime == arr[j+1].getArriveTime()){//当该系统时间有到达的进程时,输出并记录进程到达系统,该判断独立执行,与flag无关//可能有多个进程同时到达,所以用while多次判断j++;System.out.println("进程" + arr[j].getName() + "到达系统");}calculateResponseRatio(j, systemTime);//计算等待队列中所有进程的响应比,进程下标从0到j//根据系统中是否有进程在执行,进行不同操作if(flag == 1){//flag=1表示 当前有进程在执行,判断该进程是否还在执行if(arr[i].getAlreadyServiceTime() != arr[i].getServiceTime()){//如果进程i已经服务的时间 != 应该服务的时间,即进程正在执行,则输出"正在执行"System.out.println("进程" + arr[i].getName() + "正在执行");arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间}else{//如果进程i已经服务的时间 = 应该服务的时间,即进程服务结束System.out.println("进程" + arr[i].getName() + "执行结束");arr[i].setEndTime(systemTime);//记录进程i结束服务时间//计算进程的周转时间、带权周转时间arr[i].setTurnaroundTime(arr[i].getEndTime() - arr[i].getArriveTime());arr[i].setTurnaroundTimeWithRight(arr[i].getTurnaroundTime() / (double)arr[i].getServiceTime());//记录周转总时间、带权周转总时间totalTurnaroundTime += arr[i].getTurnaroundTime();totalTurnaroundTimeWithRight += arr[i].getTurnaroundTimeWithRight();//此处不要令i加1了,找下一个需要执行的进程的任务交给flag=0的语句块,FCFS算法可以直接i+1,其他算法不可以
//                  if(i+1 <= j)  i++;//执行完一个进程后,如果等待队列中还有进程,则i加1,准备执行下一个进程flag = 0;//进程执行完,flag置0,表明系统中无进程执行}}if(flag == 0)//此处不用else,因为上面flag=1时可能将flag置0,此flag=0和flag=1是可能都发生的{//flag=0表示 当前无进程在执行,如果等待队列中有进程,则执行一个进程//找到拥有最大响应比并且没有被执行的进程并执行它i = findMaxResponseRatioIndex(j);//把拥有最大响应比的进程下标赋值给i,然后执行if(arr[i].getVisited() == 0){//当 当前没有进程在执行 并且 进程i未被执行过,则执行进程i//此if判断是必要的,因为上方函数在找不到符合条件的进程时返回的i为num-1,//如果不执行if,则会反复执行进程num-1,导致算法陷入死循环System.out.println("进程" + arr[i].getName() + "开始执行");arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间arr[i].setStartTime(systemTime);//记录进程i的开始服务时间arr[i].setVisited(1);//别忘记标记进程i被访问过,否则最后一个进程每次都会进入该if反复执行flag = 1;//标志当前有进程执行}}systemTime++;//系统时间在程序末尾自动增加,表示该时刻过去System.out.println("此时正在执行进程i:" + i);System.out.println("此时等待队列尾部的是进程j:" + j);System.out.println("此时flag:" + flag);//SPF算法不能单纯的再用这个if判断是否退出算法了(不是按到达时间顺序选取进程执行的算法都不行)//因为SPF算法不是按照FCFS一样从下标为0的进程顺序执行到下标为num-1的进程//最后一个执行的进程的下标不一定是num-1,所以不能用i=num-1来判断是否全部进程都执行完毕//但是为了此处退出算法的判断所有算法都统一,本人改写了最后给下标i赋值的代码,//当全部进程都执行完毕时,令i = num-1//使得该判断方式仍然成立,所以仍然使用此判断方式if(i == num-1 && j == num-1 && flag == 0){//当j=num-1时说明全部进程都已经到达系统,//当i=num-1并且flag=0时,表示本该在执行第num-1个进程,但是现在没有进程在执行//说明第num-1个进程即最后一个进程也执行完了,可以退出算法了break;}try{Thread.sleep(1000);//模拟系统运行,制造一个时间停顿}catch(Exception e){e.printStackTrace();}System.out.println();}displayResult();//算法执行结束,展示结果System.out.println("HRRN算法执行完成!");System.out.println();}private void calculateResponseRatio(int j, int systemTime) {//计算等待队列中所有进程的响应比,进程下标从0到j,//响应比 =(等待时间+要求服务时间)/ 要求服务时间    (等待时间 = 当前系统时间 - 到达时间)for(int i = 0; i <= j; i++){arr[i].setResponseRatio( ((systemTime - arr[i].getArriveTime()) + arr[i].getServiceTime())/ (double)arr[i].getServiceTime());}}private int findMaxResponseRatioIndex(int j){//遍历此时到达系统的所有进程,找到拥有最大响应比的进程double maxResponseRatio = -1;//记录最大的响应比,初值设为一个很小的值int maxResponseRatioIndex = num-1;//记录拥有最大响应比进程的下标,默认设为等待队列中最后一个进程的下标,//当未找到 拥有最大响应比并且未被访问过的变量 时,即所有进程都被执行过时,i被赋值为num-1,//使得下方判断是否退出算法时判断可以退出算法,否则会陷入 既没有进程在执行,又不退出算法 的状态。for(int k = 0; k <= j; k++){//此时等待队列中的进程下标从0到jif(arr[k].getVisited() == 0){//如果进程k未被执行过if(arr[k].getResponseRatio() > maxResponseRatio){//如果 进程k的最大响应比 大于 记录的最大响应比,则更新记录maxResponseRatio = arr[k].getResponseRatio();maxResponseRatioIndex = k;}else if(arr[k].getServiceTime() < arr[maxResponseRatioIndex].getServiceTime() && arr[k].getResponseRatio() == maxResponseRatio){//如果响应比相同,则选择服务时间少的进程maxResponseRatio = arr[k].getResponseRatio();maxResponseRatioIndex = k;}}}return maxResponseRatioIndex;}private void displayResult(){//这个函数不方便写在Main里让每个算法用同一份函数,因为平均周转时间和平均带权周转时间两个变量是存在于算法的类中的,不在Main中System.out.println("系统运行结束,运行结果如下:");//使用式样化输出函数printf()输出信息,使信息便于观看System.out.printf("%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s\n","进程id", "进程名", "到达时间", "服务时间", "服务开始时间", "服务完成时间", "周转时间", "带权周转时间");for(int i = 0; i < num; i++){System.out.printf("%-8d \t%-8s \t%-8d \t%-8d \t%-8d \t%-8d \t%-8d \t%-8.2f\n",arr[i].getId(), arr[i].getName(), arr[i].getArriveTime(), arr[i].getServiceTime(),arr[i].getStartTime(), arr[i].getEndTime(), arr[i].getTurnaroundTime(), arr[i].getTurnaroundTimeWithRight());}averageTotalTurnaroundTime = totalTurnaroundTime / (double)num;averageTurnaroundTimeWithRight = totalTurnaroundTimeWithRight / (double)num;System.out.printf("平均周转时间:%.2f\n", averageTotalTurnaroundTime);System.out.printf("平均带权周转时间:%.2f\n", averageTurnaroundTimeWithRight);System.out.println();}void writeFile(){//将算法本次运行结果写入文件File file = new File("hrrnResult.txt");try{FileWriter fw = new FileWriter(file);fw.write("本次算法运行结果如下:\n");fw.write("进程id" + "\t进程名" + "\t到达时间" + "\t服务时间" + "\t服务开始时间" + "\t服务完成时间" + "\t周转时间" + "\t带权周转时间" + "\n");for(int i = 0; i < num; i++){fw.write(String.valueOf(arr[i].getId()) + "\t" + (arr[i].getName()) + "\t" + String.valueOf(arr[i].getArriveTime()) + "\t" + String.valueOf(arr[i].getServiceTime()) + "\t" + String.valueOf(arr[i].getStartTime()) + "\t\t" + String.valueOf(arr[i].getEndTime()) + "\t\t" + String.valueOf(arr[i].getTurnaroundTime()) + "\t" + new DecimalFormat("0.00").format(arr[i].getTurnaroundTimeWithRight()) + "\n");}fw.write("平均周转时间:" + new DecimalFormat("0.00").format(averageTotalTurnaroundTime) + "\n");fw.write("平均带权周转时间:" + new DecimalFormat("0.00").format(averageTurnaroundTimeWithRight) + "\n");fw.close();}catch(Exception e){e.printStackTrace();}System.out.println("本次算法执行结果已存入文件\"hrrnResult.txt\"中。");System.out.println();}private void quickSortArriveTime(PCB[] arr, int l, int r){//将进程块按照 到达时间 从小到大升序排序int i = l;int j = r;PCB key = new PCB();key = arr[l];if(i >= j)  return;while(i < j){while(i < j && key.getArriveTime() <= arr[j].getArriveTime())j--;arr[i] = arr[j];while(i < j && key.getArriveTime() >= arr[i].getArriveTime())i++;arr[j] = arr[i];}arr[i] = key;quickSortArriveTime(arr, l, i-1);quickSortArriveTime(arr, i+1, r);}}

RR(时间片轮转算法Round Robin):

package osProject.sjs;import java.io.*;
import java.text.DecimalFormat;
import java.util.Scanner;//时间片轮转算法Round Robin(RR)
public class RR
{int num = 0;//进程数目PCB[] arr = new PCB[100];int totalTurnaroundTime = 0;//周转总时间double averageTotalTurnaroundTime;//平均周转时间,周转总时间/进程个数double totalTurnaroundTimeWithRight = 0;//带权周转总时间double averageTurnaroundTimeWithRight;//平均带权周转时间,带权周转总时间/进程个数int timeSlice;//时间片Scanner sc;RR() {}RR(int num, PCB[] arr, Scanner sc){this.num = num;this.arr = arr;this.sc = sc;}void run(){//*************************进入时间片轮转算法(RR)*************************//readTimeSlice();//读入设定的时间片的值int timeFlag = 0;//时间片计时变量,记录进程i已经执行的时间//模拟一个系统时间,系统时间自动增加,当某进程的到达时间 等于 该时刻系统时间时,该进程进入等待队列int systemTime = 0;int i = 0;//正在运行的进程的下标,i的范围:i <= j//按照到达系统时间排序后,最后一个到达系统的进程的下标j,int j = -1;//下标从0到j的进程都在等待队列中,j的范围:0 <= j <= num-1,初始队列中无进程,则为-1int flag = 0;//用于判断系统现在是否被进程占用,flag=1时表示系统正在运行进程totalTurnaroundTime = 0;//初始化周转总时间totalTurnaroundTimeWithRight = 0;//初始化带权周转总时间
//      displayProcessInf();//算法开始执行,展示进程初始信息quickSortArriveTime(arr, 0, num-1);//进入算法后先按照进程到达时间进行升序排序//*************************系统开始运行,开始执行进程*************************//System.out.println("时间片轮转算法(RR)开始运行");while(true){//模拟进程执行,从 系统时间为0开始 到 最后一个进程执行结束System.out.println("当前时间:" + systemTime);//判断是否有进程进入系统(进入系统后进入等待队列),当有进程到达系统时,记录该进程并输出提示信息while(j+1 < num && systemTime == arr[j+1].getArriveTime()){//当该系统时间有到达的进程时,输出并记录进程到达系统,该判断独立执行,与flag无关//可能有多个进程同时到达,所以用while多次判断j++;System.out.println("进程" + arr[j].getName() + "到达系统");}//根据系统中是否有进程在执行,进行不同操作if(flag == 1){//flag=1表示 当前有进程在执行,判断该进程是否还在执行if(arr[i].getAlreadyServiceTime() != arr[i].getServiceTime()){//如果进程i已经服务的时间 != 应该服务的时间,即进程正在执行,则输出"正在执行"//如果该进程执行了一个时间片时间并且还未执行完毕,则将该进程放回等待队列,置flag=0,并重新计时//等到下一个系统时间时,在flag=0语句块中系统自动搜索下一个执行的进程,此处不要做多余操作if(timeFlag == timeSlice){//如果该进程执行了一个时间片时间并且还未执行完毕arr[i].setVisited(0);//将进程i置为未被执行过,放回等待队列flag = 0;//置当前无进程执行timeFlag = 0;//将时间片计时变量置0if(i+1 <= j)  i++;//执行完一个进程后,如果等待队列中还有进程,则i加1,准备执行下一个进程else  i = 0;//如果进程i后没有进程了,则令i = 0}else{//如果该进程未执行够一个时间片,则继续执行System.out.println("进程" + arr[i].getName() + "正在执行");//已经服务的时间和系统时间同步,应该在该时刻过去时增加,系统时间在程序末尾更新arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间timeFlag++;//记录进程i已经执行的时间 加1,该时间和 已经服务的时间 同步增加//上方部分代表该系统时刻进程已经执行完毕,此时可以判断该进程是否执行了一个时间片的时间}}else{//如果进程i已经服务的时间 = 应该服务的时间,即进程服务结束System.out.println("进程" + arr[i].getName() + "执行结束");arr[i].setEndTime(systemTime);//记录进程i结束服务时间//计算进程的周转时间、带权周转时间arr[i].setTurnaroundTime(arr[i].getEndTime() - arr[i].getArriveTime());arr[i].setTurnaroundTimeWithRight(arr[i].getTurnaroundTime() / (double)arr[i].getServiceTime());//记录周转总时间、带权周转总时间totalTurnaroundTime += arr[i].getTurnaroundTime();totalTurnaroundTimeWithRight += arr[i].getTurnaroundTimeWithRight();if(i+1 <= j)  i++;//执行完一个进程后,如果等待队列中还有进程,则i加1,准备执行下一个进程else i = 0;//如果进程i后没有进程了,则令i = 0flag = 0;//进程执行完,flag置0,表明系统中无进程执行}}if(flag == 0)//此处不用else,因为上面flag=1时可能将flag置0,此flag=0和flag=1是可能都发生的{//flag=0表示 当前无进程在执行,如果等待队列中有进程,则执行一个进程i = findNextProcess(i, j);if(arr[i].getVisited() == 0){//当 等待队列中还有进程 并且 当前没有进程未被执行过//由于到达时间在最上面j的部分筛选过了,所以此处只需要筛选是否被执行过System.out.println("进程" + arr[i].getName() + "开始执行");//RR算法中,进程会多次执行,所以只有第一次执行,即已经服务的时间为0时才记录进程的开始时间if(arr[i].getAlreadyServiceTime() == 0)  arr[i].setStartTime(systemTime);//记录进程i的开始服务时间//并且在RR算法中,记录开始服务时间要在记录已经服务时间前面,否则已经服务时间永不为0,则不会记录开始服务时间//已经服务的时间和系统时间同步,应该在该时刻过去时增加,系统时间在程序末尾更新arr[i].setAlreadyServiceTime(arr[i].getAlreadyServiceTime() + 1);//更新已经服务的时间arr[i].setVisited(1);//别忘记标记进程i被访问过,否则最后一个进程每次都会进入该if反复执行flag = 1;//标志当前有进程执行timeFlag++;}}systemTime++;//系统时间在程序末尾自动增加,表示该时刻过去System.out.println("此时正在执行进程i:" + i);System.out.println("此时等待队列尾部的是进程j:" + j);System.out.println("此时flag:" + flag);System.out.println("此时timeFlag:" + timeFlag);//SPF算法不能单纯的再用这个if判断是否退出算法了(不是按到达时间顺序选取进程执行的算法都不行)//因为SPF算法不是按照FCFS一样从下标为0的进程顺序执行到下标为num-1的进程//最后一个执行的进程的下标不一定是num-1,所以不能用i=num-1来判断是否全部进程都执行完毕//但是为了此处退出算法的判断所有算法都统一,本人改写了最后给下标i赋值的代码,//当全部进程都执行完毕时,令i = num-1//使得该判断方式仍然成立,所以仍然使用此判断方式if(i == num-1 && j == num-1 && flag == 0){//当j=num-1时说明全部进程都已经到达系统,//当i=num-1并且flag=0时,表示本该在执行第num-1个进程,但是现在没有进程在执行//说明第num-1个进程即最后一个进程也执行完了,可以退出算法了break;}try{Thread.sleep(1000);//模拟系统运行,制造一个时间停顿}catch(Exception e){e.printStackTrace();}System.out.println();}displayResult();//算法执行结束,展示结果System.out.println("RR算法执行完成!");System.out.println();}private int findNextProcess(int i, int j) {//找出下一个执行的进程 并返回此进程的下标,参数i为上一个系统时间执行完的进程下标加1 或 刚进入系统时的iif(arr[i].getVisited() == 0)  {//i是刚执行完的进程的下一个,如果i可以被执行,则直接执行进程ireturn i;}else{//否则再找其他的进程int flag = 1;//设置flag,全部进程都执行完毕时置1,否则置0int k;//遍历用临时变量for(int m = 0; m < 2; m++){//遍历两边等待序列,第一遍时从进程i开始遍历,若第一遍未找到可执行进程,则表示进程i后面的进程都执行完毕//此时再遍历第二遍等待序列,从0开始遍历,找到等待序列中所有进程,判断进程是否全部都执行完毕if(m == 0)  k = i;else k = 0;for(; k <= j; k++){//遍历等待队列中所有进程,取未被执行过中最早到达系统的进程if(arr[k].getVisited() == 0){//若进程k为被执行过,则令i = k,下一个执行进程ki = k;flag = 0;break;//找到下一个执行的进程后,退出循环}}}//若遍历完两遍等待序列后,flag仍等于1,则表示全部进程都执行完毕,未找到可执行进程,//则返回i = num-1,使得判断算法结束的语句成立if(flag == 1)  return num-1;else  return i;}}private void readTimeSlice(){//读入设定的时间片的值System.out.println("请输入本次运行算法的时间片大小:");while(true){//该while死循环为了防止输入非数字时直接退出该函数,//while的存在使得输入错误时可以重新输入,直到正确输入后break出whiletry{timeSlice = sc.nextInt();System.out.println("已设置本次运行算法的时间片大小为:" + timeSlice);System.out.println();break;}catch(Exception e){System.out.println("您输入的不是数字,请重新输入!");sc = new Scanner(System.in);}}}private void displayResult(){//这个函数不方便写在Main里让每个算法用同一份函数,因为平均周转时间和平均带权周转时间两个变量是存在于算法的类中的,不在Main中System.out.println("系统运行结束,运行结果如下:");System.out.println("本次计算采用时间片大小为:" + timeSlice);//使用式样化输出函数printf()输出信息,使信息便于观看System.out.printf("%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s \t%-8s\n","进程id", "进程名", "到达时间", "服务时间", "服务开始时间", "服务完成时间", "周转时间", "带权周转时间");for(int i = 0; i < num; i++){System.out.printf("%-8d \t%-8s \t%-8d \t%-8d \t%-8d \t%-8d \t%-8d \t%-8.2f\n",arr[i].getId(), arr[i].getName(), arr[i].getArriveTime(), arr[i].getServiceTime(),arr[i].getStartTime(), arr[i].getEndTime(), arr[i].getTurnaroundTime(), arr[i].getTurnaroundTimeWithRight());}averageTotalTurnaroundTime = totalTurnaroundTime / (double)num;averageTurnaroundTimeWithRight = totalTurnaroundTimeWithRight / (double)num;System.out.printf("平均周转时间:%.2f\n", averageTotalTurnaroundTime);System.out.printf("平均带权周转时间:%.2f\n", averageTurnaroundTimeWithRight);System.out.println();}void writeFile(){//将算法本次运行结果写入文件File file = new File("rrResult.txt");try{FileWriter fw = new FileWriter(file);fw.write("本次算法运行结果如下:\n");fw.write("本次计算采用时间片大小为:" + String.valueOf(timeSlice) + "\n");fw.write("进程id" + "\t进程名" + "\t到达时间" + "\t服务时间" + "\t服务开始时间" + "\t服务完成时间" + "\t周转时间" + "\t带权周转时间" + "\n");for(int i = 0; i < num; i++){fw.write(String.valueOf(arr[i].getId()) + "\t" + (arr[i].getName()) + "\t" + String.valueOf(arr[i].getArriveTime()) + "\t" + String.valueOf(arr[i].getServiceTime()) + "\t" + String.valueOf(arr[i].getStartTime()) + "\t\t" + String.valueOf(arr[i].getEndTime()) + "\t\t" + String.valueOf(arr[i].getTurnaroundTime()) + "\t" + new DecimalFormat("0.00").format(arr[i].getTurnaroundTimeWithRight()) + "\n");}fw.write("平均周转时间:" + new DecimalFormat("0.00").format(averageTotalTurnaroundTime) + "\n");fw.write("平均带权周转时间:" + new DecimalFormat("0.00").format(averageTurnaroundTimeWithRight) + "\n");fw.close();}catch(Exception e){e.printStackTrace();}System.out.println("本次算法执行结果已存入文件\"rrResult.txt\"中。");System.out.println();}private void quickSortArriveTime(PCB[] arr, int l, int r){//将进程块按照 到达时间 从小到大升序排序int i = l;int j = r;PCB key = new PCB();key = arr[l];if(i >= j)  return;while(i < j){while(i < j && key.getArriveTime() <= arr[j].getArriveTime())j--;arr[i] = arr[j];while(i < j && key.getArriveTime() >= arr[i].getArriveTime())i++;arr[j] = arr[i];}arr[i] = key;quickSortArriveTime(arr, l, i-1);quickSortArriveTime(arr, i+1, r);}
}

输入数据:

进程 a
到达时间 0
服务时间 13
优先级 1

进程 b
到达时间 10
服务时间 8
优先级 3

进程 c
到达时间 13
服务时间 5
优先级 5

进程 d
到达时间 16
服务时间 3
优先级 7

进程 e
到达时间 20
服务时间 1
优先级 5

时间片设置为 3

编写程序过程中遇到的问题及解决方法:

程序运行时遇到的问题

(1)    在用户使用输入功能时,若输入了非要求的数据,则会导致程序中断退出,无法继续执行程序,如果想重新输入功能需要重新运行程序,操作繁琐。

分析及解决:经过思考,决定在选择功能的代码块外加上一层while的死循环,并且仅当用户正确选择功能后才会break掉循环,并且加入try-catch检错机制,使得输入出错时不退出程序,而是要求用户重新输入。

(2)    在try-catch语句中,进入catch语句后陷入了死循环。

分析及解决:问题出现在catch中,由于Scanner对象读入了一个非目标数据,导致进入catch,但是在catch中未将Scanner对象中存储的异常数据清楚,从而导致反复进入catch。解决方法是在catch中为Scanner重新分配地址空间。

(3)    Scanner对象在一个函数中关闭后,在另一个函数中也无法再使用,重新创建新的也不行。

分析及解决:当一个类中有两个及两个以上的Scanner实例时,其中一个Scanner类的实例执行scanner.close()方法会关闭其他潜在的InputStream流。因为Scanner对象在关闭时,也会自动调用它的输入流进行关闭,也就是scanner.close()的时候,会导致System.in的关闭,导致其他Scanner的扫描器无法读取输入流,scanner不能再次获取输入。解决方法是只在主函数创建和关闭Scanner对象,其他函数若要使用Scanner对象,则以参数形式传入该函数。

(4)    发现有部分进程未执行,并且程序陷入死循环。
分析及解决:经排查,发现是因为程序中条件判断语句不完整,导致有些操作漏掉了,从而导致部分进程未执行,并且因为未执行进程导致进程中的信息未更新,从而导致程序无法达到退出的判断条件。

(5)    数据输出格式与程序中编写的要求输出的格式不同,程序未按要求输出。

分析及解决:经测试,发现是因为输出格式设置的输出间隔太小,导致程序输出时无法按照要求排列,程序自动调整后输出了。解决方法是把输出格式的间隔调大,然后程序正常输出。

(6)    所有算法用同一组数据,导致一种算法用完该组数据时,该数据中有这次算法执行的结果值残留,导致使用本组数据执行下一个算法时,残留数据可能会影响本次算法结果。

分析及解决:每次调用算法时,将数据复制一个副本传入算法,这样原数据是一直保持不改变的,每个算法使用的都是复制的副本数据,对其他算法不造成影响。

(7)    Java对象在进行复制时,并不是真正的复制出一个独立的对象,而是出现了两个对象名调用的同一块地址内容,当我改写其中一个对象的内容时,另一个对象的内容也随之改变。

分析及解决:本人在网络上搜索该问题,并学习了正确的复制对象的方法,每次创建出新的对象并为它用set方法对单个变量赋值,这样就复制除了一个独立的新对象。

(8)    在执行SPF算法时,由于需要选取服务时间最短的进程,所以我想将进程数组按照服务时间排序,但是程序执行时发现出现了错误,一个进程还未执行完就换了另一个进程执行。

分析及解决:经排查,发现在本人编写的算法中,进程运行时再对进程数组进行排序导致进程顺序出现问题,从而导致算法出错,在本人编写的算法中不能在进程执行过程中对进程数组进行排序,除非改写代码。但是我不想改写代码,就使用了另一个方法解决,在选择下一个需要执行的进程时,遍历等待序列选取合适的进程,不再使进程序列顺序发生改变。

(9)    在SPF算法中出现了既不执行进程又不退出算法的问题。

分析及解决:经排查,发现在判定算法退出时使用的是FCFS的退出判断,但是这两个算法的进程执行顺序不一致导致退出时用同一个退出判定是不可行的。但是我为了所有算法都使用统一的退出判定,改写了SPF算法的部分代码,使得该算法最后进程执行完时符合FCFS算法的退出条件,并在后面算法编写时仍使用此思路,使得其他算法的退出判定也使用同一个退出条件。

(10)    在RR算法中出现了进程还未到达系统,但是已经开始执行的问题。

分析及解决:经分析,发现是进程等待序列的进程数量出了问题,然后发现是进程等待序列的控制变量计算逻辑有问题,其他算法也有此问题,但是由于RR算法和其他算法的进程调度方式不同,所以只有RR算法会出现此问题。解决方法是改写进程等待序列的控制变量的计算方式,使其正确控制进程等待序列中的进程数量。

(11)    在RR算法中,发现周转时间的输出有问题,出现了负数。

分析及解决:经分析,发现是因为RR算法的进程执行顺序同其他算法都不一样,导致其周转时间计算结果出错,然后发现是由于算法的进程执行顺序出错,然后本人将进程的执行顺序改写正确,解决了问题。

(12)    在RR算法中,进程会多次执行,导致记录进程开始服务时间的变量会反复赋值,最后只保留最后一次运行的开始时间,但是我想要记录的不是这个时间。

分析及解决:在记录开始服务时间处加上了if判断,仅当第一次执行进程时才会记录其开始服务时间。

(13)    在调试算法输出结果到文件中时,发现“\t”的输出长度不一致。

分析及解决:经上网查阅资料后发现,“\t”是补全(8-前面字符的位数%8)的距离,也就是说前面有1个字符那么在1个字符后输出一个\t,则\t的长度为7个字符长度”,所以因为我输出\t时,前面的字符长度不同,导致\t补全的长度不同。

14
问题:使用foreach遍历对象数组时出现多种错误,如:”java.lang.NullPointerException“,还会出现遍历完后返回主函数直接进入catch块中的问题。
解决:因无法找到原因,并且实训过程中没有充足的时间去解决问题,故改用普通for循环代替foreach。
15
问题:使用Java自带的sort函数时,无论怎样修改都会出现错误,不知道错误原因。
解决:因无法找到原因,并且实训过程中没有充足的时间去解决问题,故使用自己编写的sort函数。

12.29~12.30 了解进程调度算法的大概框架和内容,进行PCB以及FCFS算法代码的编写
12.31 SPF、SPSA和HRRN算法代码的编写
1.1 RR算法代码的编写,进程信息的文件存取
1.2 算法结果输出到文件中代码的编写

进程管理系统的设计与实现 SDUT 操作系统实训 项目 Java相关推荐

  1. linux管道通信题目,操作系统实训(Linux)——习题解答、例题解析、实验指导-王红-实验实验7软中断及管道通信课案.ppt...

    操作系统实训(Linux)--习题解答.例题解析.实验指导-王红-实验实验7软中断及管道通信课案.ppt 实验7 软中断及管道通信 一.实验目的(1)掌握linux系统软中断通信的实现方法.(2)掌握 ...

  2. JavaWeb实训项目:基于SSM框架的CRM客户关系管理系统(文章最后有源码)

    JavaWeb实训项目:基于SSM框架的CRM客户关系管理系统(附部分源码) 一.项目背景 项目演示 二.项目介绍 三.涉及技术 总结 源码地址 一.项目背景 "世上本来没有CRM,大家的生 ...

  3. JAVA实训项目之学生管理系统(JDBC+GUI)

    本系统设计采用的是Java作为设计语言,MySQL作为数据库,简单来说整个系统涉及到Swing界面的开发.以及对于数据库的一些操作,查询.增加.删除等,通过上述的操作来完成相应的学生管理系统的基本功能 ...

  4. 山西高平地域文化导入美术设计实训项目的实践

    地域文化,是指某个地域的人们在特定的范围内,在自然环境的基础上,在长期的生产生活中创造的.人类活动的产物.山西高平是神农炎帝的故里,长平之战的发生地,是一个有着很深文化积淀的新兴城市,行政区域是国土面 ...

  5. 2020年Java实训项目【GUI学生信息管理系统】目录

    Java实训项目1:GUI学生信息管理系统 - 实训概述 Java实训项目2:GUI学生信息管理系统 - 系统概述 Java实训项目3:GUI学生信息管理系统 - 涉及知识点 Java实训项目4:GU ...

  6. Java实训项目1:GUI学生信息管理系统 - 实训概述

    文章目录 一.实训概述 1.实训目的 2.实训项目简介 3.项目开发思维导图 4.实训日志模板 5.实训报告模板 6.实训考核标准 一.实训概述 1.实训目的 让学生综合运用J2SE有关知识开发[学生 ...

  7. Java实训项目:GUI学生信息管理系统(2019)【下】

    Java实训项目:GUI学生信息管理系统(2019)[下] 本篇目录 六.实现步骤 13.应用程序类 14.窗口界面类(JFrame)

  8. Java实训项目:GUI学生信息管理系统(2019)【中】

    Java实训项目:GUI学生信息管理系统(2019)[中] 本篇目录 四.涉及知识点 1.Java基本语法 2.Java流程控制

  9. Java实训项目:GUI学生信息管理系统(2019)【上】

    Java实训项目:GUI学生信息管理系统(2019)[上] 本篇目录 零.实训概述 1.实训目的 2.项目简介

最新文章

  1. 要学好linux运维请从排版画图开始
  2. linux中进程的控制总结,Linux中的进程控制
  3. beta阶段第二次scrum meeting
  4. Windows 7 下 Node.js 连接 Oracle
  5. linux-修改pip包的下载源-改为国内境象提升速度
  6. Unreal4 IOS上使用第三方库和C++11 特性问题解决
  7. 《Scikit-Learn与TensorFlow机器学习实用指南》第5章 支持向量机
  8. 一加8渲染图曝光:后置三摄/五种配色可选
  9. KNN(七)--最近邻及OpenCV源码分析
  10. Kubernetes学习指南,轻松拥抱云原生
  11. 数据库(mysql、oracle、sqlserver)单表sqlserver
  12. 忽悠马云10亿,还阿里4500亿:做对事赢一场,跟对人赢一生!
  13. 大型电商数据库设计与分析
  14. win10系统(64位)3dmax2018安装与破解遇到问题
  15. redis缓存雪崩解决方案六种
  16. 主机甲和乙已建立了 TCP 连接,甲始终以 MSS=1KB 大小的段发送数据,并一直有数据 发送;乙每收到一个数据段都会发出一个接收窗口为 10KB 的确认段。若甲在 t 时刻发生超 时时拥塞窗口为
  17. IPv4掩码与掩码位数的转换
  18. 微软关闭了两种攻击途径:Office 宏、RDP 暴力破解
  19. 内存条的写入速度比硬盘快很多
  20. 计算年龄:sql计算

热门文章

  1. 跳转QQ群android代码,android 怎么跳转直接到qq群
  2. 【解读黑客】何为Rootkit?
  3. Android 前置摄像头预览与编码
  4. M 个同样的苹果放在N 个同样的盘子里,允许有的盘子空着不放的算法
  5. 云+5g +大数据 +ai_5G + AI,设备智能(第一部分)
  6. vue 给某个div设置回到顶部
  7. Axios的二次封装(简单易懂)
  8. JS实现简易画图工具
  9. NYOJ 42 一笔画
  10. ICN: Integrated crosstalk noise