目录
文章目录
前言
一、实验原理
二、实验步骤
1.创建PCB类
2.创建创建类
3.设计主窗口类
4.调度界面函数
5.算法类及其调度算法通用函数
6.进程调度算法函数
总结
前言
操作系统实验1:进程调度算法,步骤3、4在一个类中,步骤5、6在一个类中。
一、实验原理
(1)先到先服务调度算法:按照进程提交给系统的先后次序来进行调度。
(2)短作业优先调度算法:按照进程所要求的运行时间来衡量。
(3)时间片轮转调度算法:根据先来先服务排序,以一个时间片为单位,依次执行不同的进 程。
(4)优先权调度算法:按照进程的优先权来衡量。
实验要求:
二、实验步骤
1.创建PCB类
代码如下:
package os.test1;
public class PCB {
String name; //进程名/进程标识符
int runtime; //进程运行时间
int newruntime; //进程剩余运行时间(时间片轮转要用)
int arrivaltime; //进程到达时间
int newarrival; //进程再次到就绪队列队首位置时间
int priority; //进程优先级
int starttime; //进程开始运行时间
int endtime; //进程运行结束时间
int turntime; //进程周转时间
double dturntime; //带权周转时间
public PCB(String name,int priority,int runtime,int arrivaltime){
this.name=name;
this.priority=priority;
this.runtime=runtime;
this.arrivaltime=arrivaltime;
this.starttime=0;
this.endtime=0;
this.turntime=0;
this.dturntime=0;
this.newarrival=arrivaltime; //再次到达就绪队首位置默认为首次到达时间
this.newruntime=runtime; //刚开始剩余运行时间为运行时间
}
}
2.创建创建类
主要负责PCB的创建和检测已经创建好的进程PCB。
代码如下:
package os.test1;
import java.util.ArrayList;
public class Create {
public ArrayList<PCB> createPcb(ArrayList<PCB> pcbs, String name, int priority, int runtime, int arrivaltime){
//新进程进数组
PCB pcb=new PCB(name,priority,runtime,arrivaltime);
pcbs.add(pcb);
return pcbs;
}
public void check(ArrayList<PCB> pcbs){
if(pcbs.isEmpty()){
System.out.println("当前没有进程信息。");
return;
}
for(PCB cur:pcbs){
System.out.println("进程名:"+cur.name+",优先级:"+cur.priority+",需要运行时间:"+cur.runtime
+",到达时间:"+cur.arrivaltime);
}
}
3.设计主窗口类
实现三个主功能添加进程、进程调度、查看进程。
代码如下:
public class Psch {
public static void main(String args[]){
ArrayList<PCB> pcbs=new ArrayList<PCB>();
Psch.mainMenu(pcbs);
}
public static void mainMenu(ArrayList<PCB> pcbs){
Create create=new Create();
//测试用例
PCB pcb=new PCB("a",2,7,3);
PCB pcb2=new PCB("b",2,5,0);
PCB pcb3=new PCB("f",5,3,7);
PCB pcb4=new PCB("z",5,2,4);
PCB pcb5=new PCB("u",7,2,9);
pcbs.add(pcb);
pcbs.add(pcb2);
pcbs.add(pcb3);
pcbs.add(pcb4);
Scanner sc=new Scanner(System.in);
int count1=1;
while(count1==1){
System.out.println("**************************");
System.out.println("请输入你需要的服务:");
System.out.println("1.添加新进程");
System.out.println("2.选择调度算法");
System.out.println("3.查看当前进程信息");
System.out.println("0.退出");
System.out.println("**************************");
int num=sc.nextInt();
switch (num){
case 1:
String name;
int proirity;
int runtime;
int arrivaltime;
System.out.println("请输入进程名:");
name=sc.next();
System.out.println("请输入进程优先级:");
proirity=sc.nextInt();
System.out.println("进程进程运行时间:");
runtime=sc.nextInt();
System.out.println("进程进程到达时间:");
arrivaltime=sc.nextInt();
pcbs=create.createPcb( pcbs,name,proirity,runtime,arrivaltime);
break;
case 2:
Psch.dispatchMenu(pcbs);
break;
case 3:
create.check(pcbs);
break;
case 0:
count1=0;
break;
default:
System.out.println("输入错误,请重新输入!");
break;
}
}
}
4.调度界面函数
实现主窗口类下的一个主要函数:调度界面函数。
代码如下:
public static void dispatchMenu(ArrayList<PCB> pcbs){
Scanner sc=new Scanner(System.in);
Algorithm al=new Algorithm(); //实例化算法类
int count=1;
while(count==1){
PriorityQueue<PCB> useCase=al.initQueue(pcbs);
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("0.退出");
int num=sc.nextInt();
switch(num){
case 1:
al.FCFS(useCase);
break;
case 2:
al.SJF(useCase);
break;
case 3:
//定义时间片
System.out.println("请输入时间片大小:");
int timeR=sc.nextInt();
al.RR(useCase,timeR);
break;
case 4:
al.PR(useCase);
break;
case 5:
al.HRRN(useCase);
break;
case 0:
count=0;
break;
default:
System.out.println("输入错误,请重新输入!");
break;
}
}
}
}
5.算法类及其调度算法通用函数
1.算法类数据
package os.test1;
import java.util.*;
public class Algorithm {
private PCB min=null; //满足运行条件的进程
private int num=0; //一批进程周转时间和
private int start=0; //更新系统开始时间
private double nums=0; //一批带权周转时间
private int count=0; //统计一批进程的进程个数
private static Create create=new Create(); //实例化,以方便创建和增加进程
2.所有进程调度可用通用函数
代码如下:
//将传来的PCB数组转化成先以到达时间从小到大,再以进程大小从小到大排序而成的队列并返回
public PriorityQueue<PCB> ArrivalAscPri(ArrayList<PCB> pcbs) {
PriorityQueue<PCB> arrAscQueue = new PriorityQueue<>((x1,x2)->
{return x1.arrivaltime!=x2.arrivaltime?x1.arrivaltime-x2.arrivaltime
:x1.runtime-x2.runtime;});
while (!pcbs.isEmpty())
arrAscQueue.add(pcbs.remove(0));
return arrAscQueue;
}
//复制数组中的对象,并使用ArrivalAscPri函数返回优先级队列
public PriorityQueue<PCB> initQueue(ArrayList<PCB>pcbs) {
ArrayList<PCB> useCase = new ArrayList<PCB>();
for (PCB cur : pcbs){
PCB temp=new PCB(cur.name,cur.priority,cur.runtime,cur.arrivaltime);
useCase.add(temp);
}
PriorityQueue<PCB> arrAscQueue=ArrivalAscPri(useCase);
return arrAscQueue;
}
//end进程已经运行完,打印这个进程的信息
public void endPrint(PCB end){
System.out.println("进程名:"+end.name+",优先级:"+end.priority+",运行时间:"+end.runtime+",到达时间:"+
end.arrivaltime+",开始时间:"+end.starttime+",结束时间:"+end.endtime+",周转时间:"+end.turntime+
",带权周转时间:"+end.dturntime);
}
//所有进程都运行完了,打印平均周转时间和平均带权周转时间并重置数据成员参数
public void endFun(){
System.out.println("平均周转时间:"+(double)this.num/this.count+",平均带权周转时间:"+this.nums/this.count);
this.start=0;
this.nums=0;
this.count=0;
this.num=0;
this.min=null;
}
//进程已经结束,更新进程开始时间,结束时间,周转时间,带权周转时间,更新nums,num,start(下一
个进程开始时间)
public void operation(){
start = start > min.arrivaltime ? start : min.arrivaltime;
min.starttime = start;
min.endtime = min.starttime + min.runtime;
min.turntime = min.endtime - min.arrivaltime;
min.dturntime = (double) min.turntime / min.runtime;
endPrint(min);
num += min.turntime;
nums += min.dturntime;
start = min.endtime;
}
6.进程调度算法函数
1.先来先服务算法(FCFS)
代码如下:
//先来先服务算法
public void FCFS(PriorityQueue<PCB> arrAscQueue){
while(!arrAscQueue.isEmpty()){
min=arrAscQueue.remove(); //直接根据优先级队列顺序打印(先到先打印,同时到运行时间小先打印)
operation();
count++;
}
this.endFun(); //所有进程调度完成
}
2.短作业优先算法(SJF)
代码如下:
//短作业优先算法
public void SJF(PriorityQueue<PCB>arrAscQueue){
//根据运行时间大小实现短作业优先级就绪队列
PriorityQueue<PCB> arrivedAscQueue=new PriorityQueue<PCB>((x1,x2)->{return x1.runtime-x2.runtime;});
while(!arrAscQueue.isEmpty()||!arrivedAscQueue.isEmpty()){
//如果就绪队列为空并且start进程可开始运行时间小于arrAscQueue的队首元素到达时间,就进一个入就绪队列
if(arrivedAscQueue.isEmpty()&&!arrAscQueue.isEmpty()&&start<arrAscQueue.peek().arrivaltime)
arrivedAscQueue.add(arrAscQueue.remove());
if(!arrivedAscQueue.isEmpty()) { //运行就绪队列的队首元素
min=arrivedAscQueue.remove();
operation();
count++;
}
//到达时间小于下一进程开始时间就进就绪队列
while(!arrAscQueue.isEmpty()&&start>=arrAscQueue.peek().arrivaltime){
arrivedAscQueue.add(arrAscQueue.remove());
}
}
endFun();
}
3.时间片轮转算法(RR)
代码如下:
//根据剩余运行时间运行完min进程打印并设置其值和数据成员值
//只用于时间片轮转算法
public void operationRR(int minTime){
min.endtime = start + minTime;
min.turntime = min.endtime - min.arrivaltime;
min.dturntime = (double) min.turntime / min.runtime;
endPrint(min);
num += min.turntime;
nums += min.dturntime;
start = min.endtime;
}
//时间片轮转算法
public void RR(PriorityQueue<PCB>arrAscQueue,int timeR) {
PriorityQueue<PCB> newArrAscQueue= new PriorityQueue<PCB>((x1,x2)->{return x1.newarrival-x2.newarrival;});
//如果有,先把前面先到达的进程并且连续运行时间小于时间片的运行完
while(!arrAscQueue.isEmpty()&&arrAscQueue.peek().runtime<=timeR){
min=arrAscQueue.remove();
operation();
count++;
}
while(!arrAscQueue.isEmpty()||!newArrAscQueue.isEmpty()){
while(!arrAscQueue.isEmpty()&&start>=arrAscQueue.peek().arrivaltime)
newArrAscQueue.add(arrAscQueue.remove());
//找出符合算法的进程运行
if(newArrAscQueue.isEmpty()||
(!arrAscQueue.isEmpty()&&newArrAscQueue.peek().newarrival>=arrAscQueue.peek().arrivaltime)
)
min=arrAscQueue.remove();
else
min=newArrAscQueue.remove();
if(min.runtime==min.newruntime) {
start=start>min.arrivaltime?start:min.arrivaltime;
min.starttime = start;
}
int minTime=Math.min(min.runtime,min.newruntime);
if(minTime<=timeR){
operationRR(minTime);
count++;
}
else{
start+=timeR;
min.newruntime-=timeR;
min.newarrival+=(newArrAscQueue.size()+1)*timeR;
newArrAscQueue.add(min);
}
}
endFun();
}
4.动态优先级算法(PR)
代码如下:
//比较器,实现动态优先级队列
public class DynamicPriDecComparator implements Comparator<PCB> {
@Override
public int compare(PCB o1, PCB o2) {
return (start - o2.arrivaltime + o2.priority) - (start - o1.arrivaltime + o1.priority);
}
}
//更新动态优先级(start会改变)
public void updatePR(PriorityQueue<PCB> PRqueue){
PriorityQueue<PCB> temp=new PriorityQueue<>(new DynamicPriDecComparator());
while(!PRqueue.isEmpty())
temp.add(PRqueue.remove());
while(!temp.isEmpty())
PRqueue.add(temp.remove());
}
public void PR(PriorityQueue<PCB> arrAscQueue){
//优先级从大到小为高到低
PriorityQueue<PCB> newpriDecQueue= new PriorityQueue<PCB>(new DynamicPriDecComparator());
while(!arrAscQueue.isEmpty()||!newpriDecQueue.isEmpty()){
//只有进程可开始时间大于arrAscQueue队首元素到达时间才进就绪队列
while(!arrAscQueue.isEmpty()&&start>=arrAscQueue.peek().arrivaltime)
newpriDecQueue.add(arrAscQueue.remove());
//选出符合运行条件的进程
if(newpriDecQueue.isEmpty())
min=arrAscQueue.remove();
else
min=newpriDecQueue.remove();
operation();
count++;
updatePR(newpriDecQueue);
}
endFun();
}
5.高响应比算法(HRRN)
代码如下:
//😊比较器,实现高响应比优先级队列
public class RpDecComparator implements Comparator<PCB> {
@Override
public int compare(PCB o1, PCB o2) {
return (double)(start - o2.arrivaltime )/o2.runtime > (double)(start - o1.arrivaltime )/o1.runtime
?1:-1;
}
}
//更新响应比并更新队列
public void updateHRR(PriorityQueue<PCB> HRRqueue){
PriorityQueue<PCB> temp=new PriorityQueue<>(new RpDecComparator());
while(!HRRqueue.isEmpty())
temp.add(HRRqueue.remove());
while(!temp.isEmpty())
HRRqueue.add(temp.remove());
}
//高响应比优先算法
public void HRRN(PriorityQueue<PCB> arrAscQueue) {
PriorityQueue<PCB> newrpDecQueue= new PriorityQueue<PCB>(new RpDecComparator());
while(!arrAscQueue.isEmpty()||!newrpDecQueue.isEmpty()){
while(!arrAscQueue.isEmpty()&&start>=arrAscQueue.peek().arrivaltime)
newrpDecQueue.add(arrAscQueue.remove());
if(newrpDecQueue.isEmpty())
min=arrAscQueue.remove();
else
min=newrpDecQueue.remove();
operation();
updateHRR(newrpDecQueue); //更新响应比并更新队列
count++;
}
endFun();
}
总结
已经测试过了,和各位伙伴一起进步!