一.题目要求描述
本设计的目的是加深对进程概念及进程管理各部分内容的理解;熟悉进程管理中主要数据结构的设计及进程调度算法、进程控制机构、同步机构及通讯机构的实施。要求设计一个允许n个进程并发运行的进程管理模拟系统。
该系统包括有简单的进程控制、同步与通讯机构,其进程调度算法可任意选择。每个进程用一个PCB表示,其内容根据具体情况设置。各进程之间有一定的同步关系(可选)。系统在运行过程中应能显示或打印各进程的状态及有关参数的变化情况,以便观察诸进程的运行过程及系统的管理过程。
二、程序流程图及源代码注释
2.2 程序流程图
-
1.系统流程图
2.先来先服务(FCFS)算法:
3.短进程优先算法:
4.静态优先级调度算法:
5.时间片轮转调度算法:
2.2 核心函数源代码注释
1.先来先服务(FCFS)算法
void run()
{
//*************************进入先来先服务算法(FCFS)*************************//
//模拟一个系统时间,系统时间自动增加,当某进程的到达时间 等于 该时刻系统时间时,该进程进入等待队列
int systemTime = 0;
int i = 0;//正在运行的进程的下标,i的范围:i <= j
//按照到达系统时间排序后,最后一个到达系统的进程的下标j,
int j = -1;//下标从0到j的进程都在等待队列中,j的范围:0 <= j <= num-1,初始队列中无进程,则为-1
int flag = 0; //用于判断系统现在是否被进程占用,flag=1时表示系统正在运行进程
totalTurnaroundTime = 0;//初始化周转总时间
totalTurnaroundTimeWithRight = 0;//初始化带权周转总时间
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(i+1 <= j) i++;//执行完一个进程后,如果等待队列中还有进程,则i加1,准备执行下一个进程
if(arr[i].getVisited() == 0)
{ //当等待队列中还有进程 并且 当前没有进程未被执行过
//由于到达时间在最上面j的部分筛选过了,所以此处只需要筛选是否被执行过
if(i==0){
//判断第一个进程到达的时间是否等于系统时间,等于的话才开始执行第一个进程
if(arr[i].getArriveTime()==systemTime){
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;//标志当前有进程执行
}
}
//以下为除第一个进程以外的进程,flag==0的时候只要 该进程到达了且未被访问则开始执行
else {
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++;//系统时间在程序末尾自动增加,表示该时刻过去
//根据flag的值进行某时刻状态的记录
if(flag==0){
System.out.println("此时没有正在执行的进程");
System.out.println("此时等待队列尾部没有进程");
System.out.println("此时flag:" + flag);
}else {
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();
}
2.短进程优先(SPF)算法
void run()
{
//*************************进入短进程优先算法(SPF)*************************//
//模拟一个系统时间,系统时间自动增加,当某进程的到达时间 等于 该时刻系统时间时,该进程进入等待队列
int systemTime = 0;
int i = 0;//正在运行的进程的下标,i的范围:i <= j
//按照到达系统时间排序后,最后一个到达系统的进程的下标j,
int j = -1;//下标从0到j的进程都在等待队列中,j的范围:0 <= j <= num-1,初始队列中无进程,则为-1
int 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为0,
//如果不执行if,则会反复执行进程num-1,导致算法陷入死循环
if(i==0){
if (arr[i].getArriveTime() == systemTime) {
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;//标志当前有进程执行
}}
else{
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++;//系统时间在程序末尾自动增加,表示该时刻过去
if(flag==0){
System.out.println("此时没有队列执行");
System.out.println("此时等待队列尾部的是进程j:" + j);
System.out.println("此时flag:" + flag);
}
if(flag==1) {
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 == 0 && j == num-1 && flag == 0)
{//当j=num-1时说明全部进程都已经到达系统,
//当i=0并且flag=0时,表示本该在执行第num-1个进程,但是现在没有进程在执行,所以i被自动初始化为0
//说明第num-1个进程即最后一个进程也执行完了,可以退出算法了
break;
}
try
{
Thread.sleep(1000);//模拟系统运行,制造一个时间停顿
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println();
}
3.静态级调度(SPSA)算法
//*************************进入静态优先级调度算法(SPSA)*************************//
void run()
{
readPriority();//读入各进程的优先级
//模拟一个系统时间,系统时间自动增加,当某进程的到达时间 等于 该时刻系统时间时,该进程进入等待队列
int systemTime = 0;//初始化系统时间
int i = 0;//设置正在运行的进程的下标,i的范围:i <= j
//按照到达系统时间排序后,最后一个到达系统的进程的下标j,
int j = -1;//下标从0到j的进程都在等待队列中,j的范围:0 <= j <= num-1,初始队列中无进程,则为-1
int 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()) //可能有多个进程同时到达,所以用while多次判断
{
j++;
//当该系统时间有到达的进程时,输出并记录进程到达系统,该判断独立执行,与flag无关
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(i+1<=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++;//系统时间在程序末尾自动增加,表示该时刻过去
if(flag==0){
System.out.println("此时没有正在执行的进程");
System.out.println("此时等待队列尾部没有进程");
System.out.println("此时flag: "+flag);
}
else{
System.out.println("此时正在执行进程i:" + i);
System.out.println("此时等待队列尾部的是进程j:" + j);
System.out.println("此时flag:" + flag);
}
//SPF算法不能单纯的再用这个if判断是否退出算法了(不是按到达时间顺序选取进程执行的算法都不行)
//最后一个执行的进程的下标不一定是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();
}
4.轮转调度(RR)算法
void run()
{
//进入时间片轮转算法(RR)
quickSortArriveTime(arr, 0, num-1);//进入算法后先按照进程到达时间进行升序排序
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,初始队列中无进程,则为-1
int flag = 0;//用于判断系统现在是否被进程占用,flag=1时表示系统正在运行进程
totalTurnaroundTime = 0;//初始化周转总时间
totalTurnaroundTimeWithRight = 0;//初始化带权周转总时间
//系统开始运行,开始执行进程
System.out.println("时间片轮转算法(RR)开始运行");
while(true)
{
//模拟进程执行,从 系统时间为0开始 到 最后一个进程执行结束
System.out.println("当前时间:" + systemTime);
//判断是否有进程进入系统(进入系统后进入等待队列),当有进程到达系统时,记录该进程并输出提示信息
while(j+1 < num && systemTime == arr[j+1].getArriveTime())
{//当该系统时间有到达的进程时,输出并记录进程到达系统
//可能有多个进程同时到达,所以用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;//将时间片计时变量置0
if(i+1 <= j) i++;//执行完一个进程后,如果等待队列中还有进程,则i加1,准备执行下一个进程
else i = 0;//如果进程i后没有进程了,则令i = 0和flag
}
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 = 0
flag = 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++;//系统时间在程序末尾自动增加,表示该时刻过去
if(flag==0){
System.out.println("此时没有正在执行的进程");
System.out.println("此时等待队列队尾没有进程");
System.out.println("此时flag"+flag);
// System.out.println("此时timeflag"+timeFlag);
}
else {
System.out.println("此时正在执行进程i:" + i);
System.out.println("此时等待队列尾部的是进程j:" + j);
System.out.println("此时flag:" + flag);
System.out.println("此时timeFlag:" + timeFlag);
}
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();
}
3.程序设计
1)先来先服务(FCFS)算法
2)短进程优先算法
3)静态级优先调度算法
存入文档
4)时间片轮转算法
4.总结
选题是进程管理系统设计,由一个人独立完成从需求分析、结构设计、算法设计、运行测试、代码优化、实验总结六个部分,分别对FCFS算法,SPF算法,SPSA算法,RR算法进行设计。虽然实验程序仍然有所不足,但是在实验和设计的过程中也是收获颇丰,为以后的学习积累了经验。以下是每个算法的问题和解决方案以及心得:
先来先服务算法
①时间为0时没有进程到达但是进程已经开始执行,并且后面进程真正到达时又会执行一遍
②两个进程间如果有时间间隔并且间隔内没有进程在执行,则第二个进程不会等到到达才执行,且正在执行的进程i却也会显示和变化
③每个时间点的状态如果不判断,就算没有进程职系那个则一直会有显示正在执行的是该时刻进程的i
④等待队列进程增加了但是却不会继续执行下一个等待队列尾部的进程
短进程优先算法
1、在后期的调试中,发现第一个进程会在系统时间为0时开始执行,之后在设置好的开始时间又会执行一遍,后面在第一个进程中设定好需要系统时间等于开始时间才会执行后面的一系列代码;
2、进程有时候会死锁,在设置退出算法的条件时考虑的不全面。
静态优先级调度算法
在设计静态优先调度算法时,主要从以下方面考虑:
1. 考虑任务优先级:在实际应用中,任务的优先级可能会受到多个因素的影响,因此需要根据实际情况确定任务的优先级算法,出于这个考虑,在本次实验中我们可以根据考虑服务时间等因素自己设置系统的进程优先级,并设置了findMaxPriorityIndex()函数允许系统通过遍历自行找到最大优先级的进程。
2. 调度算法的实现:在实现调度算法时,需要考虑如何高效地对任务进行排序,并且需要保证算法的正确性和可靠性,故在该系统中设置quickSortArriveTime()使进程按到达时间升序排列。
3. 关于调度效率的优化:静态优先调度算法的调度效率可能会受到多个因素的影响,例如任务的数量、任务的执行时间等,因此我们需要针对不同的应用场景进行优化,以提高算法的调度效率,但在这一方面,在本次设计中,个人考虑或许不太全面,故在给出些许的程序可能在会出现些许问题,说明该设计还有优化的空间。
时间片轮转调度算法
非抢占式轮转调度算法RR中,系统根据FCFS策略,将所有就绪进程排成一个就绪队列。就绪队列上的每个进程每次仅运行一个时间片。时间片的选择对系统性能有很大影响。
若选择很小的时间片,将有利于短作业,但会增加系统开销;
若时间片选择太长,RR算法退化为FCFS算法,无法满足短作业和交互式用户的需求。
在调试程序过程中,出现了进程还未到达但已开始执行的问题。经分析,是等待队列的进程数量计算错误;发现周转时间输出为负数,是由于进程的执行顺序出错;发现由于进程在一个时间片时间后未执行完毕而出现多次执行,使得进程开始服务时间会被反复赋值,所以在记录开始服务时间代码处加上if条件判断,只记录进程第一次执行的开始服务时间。