目录
前言
进程调度简介
流程图
代码实现
前言
本文主要介绍了操作系统进程调度中的两种—动态优先权调度和时间片轮转调度,包含对操作系统进程调度的基本介绍,两种调度方法的流程图,和代码实现三个部分。以下内容均为个人见解,才疏学浅,如有错误,欢迎大家指正指导,联系方式在最下面。
一、进程调度的介绍
- 在我们日常生活中,不论是手机还是电脑,我们每天都要打开很多应用,那么这时,计算机是怎么分配资源,处理机又是怎么运行的呢?是优先处理一个较短的任务?还是雨露均沾,每个任务都并发轮转执行呢?这就是操作系统的进程调度!
- 一个合理的调度算法对 CPU 的利用率、程序的总体运行效率、不同任务间的公平性起着决定性的作用,这并不是一件容易的事情,因为 CPU
的算力是各进程所需的资源,但它非常有限,于是人们发明了许多不同的调度策略。
考虑到不同任务的耗时和优先级两项指标,一般可以分为两大类策略: 非抢占式调度和抢占式调度; 大学生活中,主要有以下六种主流的调度方法:
1.先来先服务型(FIFO–First Come First Served)
2.短作业优先(SJF–Short Job First)
3.时间片轮转法(RR–Round-Robin)
4.高相应比优先(HRRN–Highest Response Ratio Next)
5.优先级调度算法
6.多级反馈队列调度算法 本文主要介绍第三种和第五种
二、流程图
三.代码实现
首先,我们需要创建一个PCB(Process Control Block)来对进程进行一些属性的设定和管理。
package yangchuang;
/*
PCB,进程控制块类,是操作系统中最重要的记录性数据结构,操作系统利用进程控制块,实现对进程的调度;
PCB中保存进程的一些基本信息,一般包括但不局限于:程序ID,特征信息,进程状态,优先级,通信信息等。
*/
public class PCB {
int id;
int runtime;//进程需要运行的总时间
String status;
int prioritylevel;
int cputime;//当前进程已经运行的时间
int numberofslice;//进程所需要的时间片数
int cpuofslice;//进程已经占用的cpu的时间片数
int arrivetime;//进程的到达时间
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getRuntime() {
return runtime;
}
public void setRuntime(int runtime) {
this.runtime = runtime;
}
public int getPrioritylevel() {
return prioritylevel;
}
public void setPrioritylevel(int prioritylevel) {
this.prioritylevel = prioritylevel;
}
public int getCputime() {
return cputime;
}
public int getArrivetime() {
return arrivetime;
}
public void setArrivetime(int arrivetime) {
this.arrivetime = arrivetime;
}
public void setCputime(int cputime) {
this.cputime = cputime;
}
public void PriorityMinusOne(){
prioritylevel--;
}
public int getNumberofslice() {
return numberofslice;
}
public void setNumberofslice(int numberofslice) {
this.numberofslice = numberofslice;
}
public int getCpuofslice() {
return cpuofslice;
}
public void setCupofslice(int cupofslice) {
this.cpuofslice = cupofslice;
}
public PCB(int id, int runtime, int prioritylevel,String status, int arrivetime) {
this.id = id;
this.runtime = runtime;
this.prioritylevel = prioritylevel;
this.status = status;
this.arrivetime = arrivetime;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public PCB(int id, int numberofslice) {
this.id = id;
this.numberofslice = numberofslice;
}
public PCB(int id, int runtime, int prioritylevel, String status) {
this.id = id;
this.runtime = runtime;
this.prioritylevel = prioritylevel;
this.status=status;
}
public PCB(int id, String status, int cputime, int numberofslice) {
this.id = id;
this.status = status;
this.cputime = cputime;
this.numberofslice = numberofslice;
}
public PCB(){}
}
package yangchuang;;
import java.util.Scanner;
import java.util.Random;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;
public class OperatingSystem {
public static void main(String[] args) {
while (true) {
System.out.println("1------Priority law");
System.out.println("2------Rotation method");
System.out.println("Please enter your choice:");
Scanner input = new Scanner(System.in);
int choice = input.nextInt();
switch (choice) {
case 1:
System.out.println("使用优先权法");
PriorityLaw();
System.exit(0);
case 2:
System.out.println("使用轮转法");
Rotationmethod();
System.exit(0);
default:
System.out.println("您的输入有误,请重新输入");
}
}
}
public static void PriorityLaw() {
Scanner input = new Scanner(System.in);
Random rand = new Random();
int number = rand.nextInt(5) + 4;
System.out.println("The number of processes is:" + number);
PCB[] m = new PCB[number];
ArrayList<PCB> array = new ArrayList<PCB>();//就绪队列
ArrayList<PCB> array2 = new ArrayList<PCB>();//就绪队列
ArrayList<PCB>FinishedArray=new ArrayList<PCB>();//用来存放已经完成的进程
int[] test = RandomNumberNoRepeat(number,10);
//创建number个进程,分配PCB,并用随机数为它们分配运行时间和优先等级
for (int i = 0; i < number; i++) {
m[i] = new PCB(i+1,rand.nextInt(20) + 1,test[i],"Ready",rand.nextInt(10)+1);
array2.add(m[i]);
}
System.out.println("整个过程中进程的基本情况:");
SortbypriorityAndArrivetime(array2);
Print01(array2);
int time=array2.get(0).arrivetime;
System.out.println("--------------------开始--------------------");
System.out.println("当time小于"+time+"的时候,没有进程到达");
while (FinishedArray.size()!=number) {
if (!judge(array2, time)) {
System.out.println("----------" + time + "时刻没有新的进程到达" + "----------");
} else {
for (int i = 0; i < array2.size(); i++) {
if (array2.get(i).getArrivetime() == time) {
System.out.println(time + "时刻,进程" + array2.get(i).getId() + "到达");
array.add(array2.get(i));
}
}
}
System.out.println("--------------------" + time + "时刻,就绪队列:" + "--------------------");
if (array.size() == 0) {
System.out.println("此时就绪队列为空");
} else {
SortaccordPriority(array);
Print01(array);
System.out.println("队头进程 " + array.get(0).getId() + " 获得cpu,开始执行,其他进程处于就绪状态");
array.get(0).setStatus("running");
Print01(array);
System.out.println("进程" + array.get(0).getId() + "的优先级数减三");
System.out.println("prioritylevel=" + array.get(0).getPrioritylevel() + "-3");
System.out.println("进程" + array.get(0).getId() + "所需的CPU时间减1" );
System.out.println("runtime=" + array.get(0).getRuntime() + "-1" );
array.get(0).prioritylevel -= 3;
array.get(0).runtime -= 1;
System.out.println("--------------------一个时刻结束--------------------");
if (array.get(0).runtime <= 0) {
System.out.println("进程 " + array.get(0).getId() + " 执行完毕,从内存中退出");
FinishedArray.add(array.get(0));
array.remove(0);
} else {
array.get(0).setStatus("Ready");
//当前进程还要继续执行,需要回到就绪队列,按照优先级的大小更新就绪队列
SortaccordPriority(array);
}
time++;
}
}
System.out.println("内存中的全部进程执行完毕,就绪队列为空");
System.out.println("--------------------结束--------------------");
}
public static void Rotationmethod(){
Random rand = new Random();
int number = rand.nextInt(5) + 4;
System.out.println("The number of processes is:" + number);
PCB[] m = new PCB[number];
ArrayList<PCB> array = new ArrayList<PCB>();//一个空的集合对象
int[] test = RandomNumberNoRepeat(number,20);
//按照进程的先后建立顺序进入就绪队列,并初始化
for(int i=0; i<number; i++){
m[i]=new PCB();
m[i].setId(i+1);
m[i].setNumberofslice(test[i]);
m[i].setCupofslice(0);
m[i].setStatus("Ready");
array.add(m[i]);
}
System.out.println("整个过程中,所有进程的基本情况如下:");
Print02(array);
System.out.println("--------------------开始--------------------");
while(!isFinish02(array)){
System.out.println("队头进程 " + array.get(0).getId() + " 获得cpu,开始执行,其他进程处于就绪状态");
array.get(0).setStatus("Running");
Print02(array);
System.out.println("进程 "+array.get(0).getId()+" 所需的时间片数减1");
System.out.println("numberofslice="+array.get(0).getNumberofslice()+"-1");
System.out.println("进程 "+array.get(0).getId()+" 已占用的CPU时间片数加1");
System.out.println("cpuofslice="+array.get(0).getCpuofslice()+"+1");
array.get(0).cpuofslice++;
array.get(0).numberofslice--;
System.out.println("--------------------一个时间片结束,开始轮转--------------------");
if(array.get(0).getNumberofslice()==0){
System.out.println("进程 "+array.get(0).getId()+"执行完毕,从内存中退出");
array.remove(0);
}else{
array.get(0).setStatus("Ready");
Reorder(array);
Print02(array);
}
}
System.out.println("内存中的全部进程执行完毕,就绪队列为空");
System.out.println("--------------------结束--------------------");
}
/*
方法Reorder实现将列表中的第一个元素放置末尾(其他位置的元素依次向前平移)
*/
public static void Reorder(ArrayList<PCB> array){
for(int i=0;i<array.size()-1;i++){
Collections.swap(array,i,i+1);
}
}
/*
SortaccordPriority方法:根据优先级数对进程进行排序
*/
public static void SortaccordPriority(ArrayList<PCB> array){
Collections.sort(array, new Comparator<PCB>() {
public int compare(PCB o1, PCB o2) {
if (o1.getPrioritylevel() - o2.getPrioritylevel() > 0) {
return 1;
} else {
return -1;
}
}
});
}
/*
SortaccordArriveTime方法:根据进程到达时间对进程进行排序
*/
public static void SortaccordArriveTime(ArrayList<PCB> array){
Collections.sort(array, new Comparator<PCB>() {
public int compare(PCB o1, PCB o2) {
if (o1.getArrivetime() - o2.getArrivetime() > 0) {
return 1;
} else {
return -1;
}
}
});
}
/*
isFinish方法用来判断当使用优先权法的时候就绪队列中的所有进程是否全部运行结束
*/
public static boolean isFinish01(ArrayList<PCB> pcb) {
boolean flag = true;
for (PCB p : pcb) {
if (p.runtime != 0) {
flag = false;
break;
}
}
return flag;
}
/*
方法用来判断使用轮转法的时候就绪队列中的所有进程是否全部运行结束
*/
public static boolean isFinish02(ArrayList<PCB> pcb){
boolean flag = true;
for (PCB p : pcb) {
if (p.numberofslice != 0) {
flag = false;
break;
}
}
return flag;
}
/*
judge方法用来判断在time时刻有没有新的进程到达;
*/
public static boolean judge(ArrayList<PCB> array,int time){
boolean flag=false;
for(int i=0;i< array.size();i++){
if(array.get(i).getArrivetime()==time){
flag=true;
}
}
return flag;
}
/*
Random方法:生成特定范围的特定个数个随机数
*/
public static int[] RandomNumberNoRepeat(int number,int bound) {
//创建一个产生随机数的对象
Random r = new Random();
//创建一个存储随机数的集合
Vector<Integer> v = new Vector<Integer>();
//定义一个统计变量
int count = 0;
while (count < number) {
int number2 = r.nextInt(bound) + 1;
//判断number是否在集合中存在
if (!v.contains(number2)) {
//不在集合中,就添加
v.add(number2);
count++;
}
}
int[] test = new int[number];
for (int i = 0; i < number; i++) {
test[i] = v.get(i);
}
return test;
}
/*
Print方法:输出就绪队列的基本情况
*/
public static void Print01(ArrayList<PCB> array){
System.out.println("id status prioritylevel runtime arrivetime");
for (int i = 0; i < array.size(); i++) {
System.out.println(array.get(i).getId()+" " + array.get(i).getStatus()+" " +array.get(i).getPrioritylevel()+" "+ array.get(i).getRuntime()+" "+array.get(i).getArrivetime());
}
}
public static void Print02(ArrayList<PCB> array) {
System.out.println("id status numberofslice cpuslice");
for (int i = 0; i < array.size(); i++) {
System.out.println(array.get(i).getId()+" " +array.get(i).getStatus()+" " +array.get(i).getNumberofslice() + " " + array.get(i).getCpuofslice());
}
}
public static void SortbypriorityAndArrivetime(ArrayList<PCB> Array) {
Array.sort(Comparator.comparing(PCB::getArrivetime).thenComparing(PCB::getPrioritylevel));
}
}
主函数中包括优先级调度和时间片轮转调度两个算法的代码
注:在本案例中,我对案例进行了一些相应的简化
1.无I/O请求
2.RR算法中进程按照创建的顺序先后进入了就绪队列,然后统一开始执行
程序的运行截图:
/*
由于中间的截图实在太长,所以这里就只放了一个开始的和一个结束的图片
另外,由于本人不会控制Java中的输出格式,所以垂直输出的时候很不对齐,希望懂得大佬可以教教孩子
*/
/*
有没有懂输出格式的大佬教教孩子吧qaq
*/
总结
在我设定的背景下,这两个代码其实不是很难,但是中途还是遇到了很多不会的地方,经过层层调试才最后能跑出来哈哈哈,至今还被输出格式的问题所深深困扰,大家一起努力吧。联系信息在下面,欢迎指正我的错误并一起探讨。
qq:2394358697
邮箱:2394358697@qq.com