文章目录

  • ​​一、实验需求​​
  • ​​二、需求分析​​
  • ​​三、效果展示​​
  • ​​(1)FCFS 调度算法​​
  • ​​(2)SJF 调度算法​​
  • ​​(3)HRRN 调度算法​​
  • ​​(4)综合对比​​
  • ​​四、具体代码​​

一、实验需求

设计一个有N个进程的进程调度程序,实现先来先服务调度算法,
,短进程优先调度算法,动态最高优先数优先调度算法。

二、需求分析

进程对象的信息抽象成此PCB类

【操作系统】代码实践:先来先服务调度算法(FCFS),短进程优先调度算法(SJF),高响应比优先调度算法(HRRN)_调度算法


为PCB类编写常用Getter/Setter,构造方法(利用random随机数实现进程实际情况中的随机性),并模拟实现进程运行及阻塞时对应时间属性值的动态变化(自减1)等等。

【操作系统】代码实践:先来先服务调度算法(FCFS),短进程优先调度算法(SJF),高响应比优先调度算法(HRRN)_操作系统_02

1、FCFS算法最容易实现,因此只需判断当前时间time的值,是否等于进程序列中的第一个进程的到达时间即可,并不断输出当前时间和进程执行情况,例如其执行时间和剩余时间,最后再提示进程执行完毕,并输出周转时间,在序列中删除此进程结点等等。

2、其次是SJF算法,此算法需额外设置一个就绪进程序列,根据当前time值,将已经达到执行开始时间的进程放入进程的就绪队列,并删除在原进程序列中的此进程结点,模拟进程的状态变化与多队列机制,当就绪队列中有进程且数量不为一个时,则对此就绪队列的进程按照进程执行时间从小到大排序,并记录此次最优先进程(即最短进程的pid),则在下轮进行就绪进程队列的排序时,便可根据第一个队列中进程结点的pid是否为之前记录的pid得知进程是否被抢占,从而输出提示信息,进而输出其他信息。

3、最后,相对较麻烦的是HRRN算法,此算法,与SJF算法的实现类似,主要区别是,将SJF算法中就绪进程队列的排序依据,从进程执行时间最短,转为进程优先级最高,并额外再增加一个进程阻塞队列(根据实验要求),而阻塞队列也是根据阻塞的开始时间,与阻塞的过程时间来与当前time时间值进行判断的,因此,在SJF算法的基础上,HRRN算法的实现也就变的不再相对复杂,因此一开始声明的HRRN的复杂是相对于从0开始编写的复杂性。

三、效果展示

具体执行结果如下:

【操作系统】代码实践:先来先服务调度算法(FCFS),短进程优先调度算法(SJF),高响应比优先调度算法(HRRN)_算法_03

(1)FCFS 调度算法

【操作系统】代码实践:先来先服务调度算法(FCFS),短进程优先调度算法(SJF),高响应比优先调度算法(HRRN)_操作系统_04

(2)SJF 调度算法

【操作系统】代码实践:先来先服务调度算法(FCFS),短进程优先调度算法(SJF),高响应比优先调度算法(HRRN)_算法_05

(3)HRRN 调度算法

(还为实现完整,这只是简单的优先级调度算法,优先数不具有动态变化性)

(内容较多,只截取部分)

【操作系统】代码实践:先来先服务调度算法(FCFS),短进程优先调度算法(SJF),高响应比优先调度算法(HRRN)_运行时间_06

(4)综合对比

(情况随机,只截取一张图。其实此处只有HRRN算法中考虑了阻塞时间,而前两种算法并未考虑,因此,由于此变量不唯一,因此此情况下的比较也无意义,但可以直观地显示结果,也可以改进此程序代码,赋予其真正的意义)

【操作系统】代码实践:先来先服务调度算法(FCFS),短进程优先调度算法(SJF),高响应比优先调度算法(HRRN)_调度算法_07

四、具体代码

class PCB {
private int pid; // 进程id
private int priority; // 进程优先级
private int arrTime; // 到达时间
private int allTime; // 还需运行时间
private int cpuTime; // 已运行时间
private int startBlockTime; // 开始阻塞时间
private int blockTime; // 阻塞时间
private String state; // 状态

public PCB(int pid, int priority, int arrTime, int allTime, int cpuTime, int startBlockTime, int blockTime, String state) {
this.pid = pid;
this.priority = priority;
this.arrTime = arrTime;
this.allTime = allTime;
this.cpuTime = cpuTime;
this.startBlockTime = startBlockTime;
this.blockTime = blockTime;
this.state = state;
}

public int getPid() {
return pid;
}

public void setPid(int pid) {
this.pid = pid;
}

public int getPriority() {
return priority;
}

public void setPriority(int priority) {
this.priority = priority;
}

public int getArrTime() {
return arrTime;
}

public void setArrTime(int arrTime) {
this.arrTime = arrTime;
}

public int getAllTime() {
return allTime;
}

public void setAllTime(int allTime) {
this.allTime = allTime;
}

public int getCpuTime() {
return cpuTime;
}

public void setCpuTime(int cpuTime) {
this.cpuTime = cpuTime;
}

public int getStartBlockTime() {
return startBlockTime;
}

public void setStartBlockTime(int startBlockTime) {
this.startBlockTime = startBlockTime;
}

public int getBlockTime() {
return blockTime;
}

public void setBlockTime(int blockTime) {
this.blockTime = blockTime;
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

/**
* HRRN 执行情况模拟
*/
public void show_HRRN() {
System.out.println("进程:" + pid +
" 优先级:" + priority +
" 到达时间:" + arrTime +
" 还需运行时间:" + allTime +
" 已运行时间:" + cpuTime +
" 开始阻塞时间:" + startBlockTime +
" 阻塞时间:" + blockTime +
" 状态:" + state);
}

/**
* SJF FCFS 执行情况模拟
*/
public void show_SJF_FCFS() {
System.out.println("进程:" + pid +
"正在执行,到达时间:" + arrTime +
" 还需运行时间:" + allTime +
" 已运行时间:" + cpuTime);
}

public void toBlock() {
state = "Block";
}

public void toRun() {
state = "Run";
}

public void toFinish() {
state = "Finish";
}

public void toReady() {
state = "Ready";
}

public void running() { // 进程运行时的状态变化
allTime -= 1;
cpuTime += 1;
}

public void toStartBlock() { // 进程将要开始阻塞时的状态变化
if (startBlockTime > 0) {
startBlockTime -= 1;
}
}

public void blocking() { // 进程阻塞时的状态变化
if (blockTime > 0) {
blockTime -= 1;
}
priority += 1;
}
}

public class Main {
/**
* 初始化进程,生成四个进程并按到达时间讲它们放入列表 list
* @param num
*/
public static List<PCB> init(int num) {
List<PCB> list = new ArrayList<PCB>();
for (int i = 0; i < num; i++) {
// 构造参数:进程id,优先级,到达时间,还需运行时间,
// 已运行时间,开始阻塞时间,阻塞时间,状态
list.add(new PCB(i, random(1, 10), random(1, 15), random(1, 10),
0, random(5, 10), random(1, 10), "Ready"));
}

// 将各进程按 到达时间 从小到大排列
for (int i = 0; i < list.size() - 1; i++) {
for (int j = i + 1; j < list.size(); j++) {
if (list.get(i).getArrTime() > list.get(j).getArrTime()) {
PCB temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
}
return list;
}

public static int random(int m, int n) {
Random random = new Random();
return (int) Math.round(random.nextDouble() * n) + m;
}

/**
* 先来先服务算法
* @param list
*/
public static int FCFS(List<PCB> list) {
int time = 0;
while (true) {
System.out.println("time: " + time);
PCB pcb = list.get(0);
if (time >= pcb.getArrTime()) {
pcb.running();
pcb.show_SJF_FCFS();
if (pcb.getAllTime() == 0) {
System.out.println("进程" + pcb.getPid() + "执行完毕,周转时间:" +
(time - pcb.getArrTime()) + "\n");
list.remove(list.get(0));
}
}
time += 1;
if (list.size() == 0) {
return --time;
}
}
}

/**
* 抢占式短作业优先
* @param list
*/
public static int SJF(List<PCB> list) {
List<PCB> readyList = new ArrayList<PCB>(); // 就绪队列
int time = 0;
int pid = 0;
while (true) {
int readyListLength = readyList.size();
System.out.println("time: " + time);

if (list.size() > 0) {
int i = 0;
while (true) { // 将进程放入就绪队列,就绪队列的第一个是正在执行的进程
if (time == list.get(i).getArrTime()) {
readyList.add(list.get(i));
list.remove(list.get(i));
pid = readyList.get(0).getPid(); // 获取就绪队列第一个进程的ID
i -= 1;
}
i += 1;
if (i >= list.size()) {
break;
}
}
}

if (readyList.size() >= 2 && readyList.size() != readyListLength) { // 判断就绪队列中最短的作业
readyListLength = readyList.size();
for (int i = 0; i < readyList.size() - 1; i++) {
for (int j = i + 1; j < readyList.size(); j++) {
if (readyList.get(i).getAllTime() > readyList.get(j).getAllTime()) {
PCB temp = readyList.get(i);
readyList.set(i, readyList.get(j));
readyList.set(j, temp);
}
}
}
}

if (readyList.size() > 0) { // 执行进程
if (pid != readyList.get(0).getPid()) { // 如果正在执行的进程改变,则发送抢占
System.out.println("发生抢占,进程" + readyList.get(0).getPid() + "开始执行");
pid = readyList.get(0).getPid();
}
readyList.get(0).running();
readyList.get(0).show_SJF_FCFS();
if (readyList.get(0).getAllTime() == 0) {
System.out.println("进程" + readyList.get(0).getPid() + "执行完毕,周转时间:" + (time - readyList.get(0).getArrTime() + 1));
readyList.remove(readyList.get(0));
if (readyList.size() > 0) {
pid = readyList.get(0).getPid();
}
}
}
time += 1;
if (readyList.size() == 0 && list.size() == 0) {
break;
}
}
return --time;
}

public static int HRRN(List<PCB> list) { // 动态最高优先数优先
List<PCB> readyList = new ArrayList<PCB>(); // 就绪队列
List<PCB> blockList = new ArrayList<PCB>(); // 阻塞队列
int time = 0;
int pid = 0;
while (true) {
System.out.println("time: " + time);
if (list.size() > 0) {
int i = 0;
while (true) { // 将进程放入就绪队列
if (time == list.get(i).getArrTime()) {
readyList.add(list.get(i));
list.remove(list.get(i));
pid = readyList.get(0).getPid();
i -= 1;
}
i += 1;
if (i >= list.size()) {
break;
}
}
}

for (int i = 0; i < readyList.size() - 1; i++) { // 将就绪队列的进程按优先级大小排列
for (int j = i + 1; j < readyList.size(); j++) {
if (readyList.get(i).getPriority() < readyList.get(j).getPriority()) {
readyList.get(i).toReady();
PCB temp = readyList.get(i);
readyList.set(i, readyList.get(j));
readyList.set(j, temp);
}
}
}

if (readyList.size() > 0) { // 执行过程
if (pid != readyList.get(0).getPid()) {
System.out.println("发生抢占,进程" + readyList.get(0).getPid() + "开始执行");
pid = readyList.get(0).getPid();
}
if (readyList.get(0).getStartBlockTime() > 0 || readyList.get(0).getBlockTime() <= 0) {
readyList.get(0).toRun();
readyList.get(0).running();
readyList.get(0).toStartBlock();
}
for (int i = 1; i < readyList.size(); i++) {
readyList.get(i).setPriority(readyList.get(i).getPriority() + 1);
readyList.get(i).toStartBlock();
}
}

if (blockList.size() > 0) { // 阻塞队列
blockList.forEach(pcb -> {
pcb.blocking();
});
}

readyList.forEach(pcb -> {
pcb.show_HRRN();
});

blockList.forEach(pcb -> {
pcb.show_HRRN();
});

if (readyList.size() > 0) { // 当进程开始阻塞事件为0,将进程放入阻塞队列
int i = 0;
while (true) {
if (readyList.size() > 0) {
if (readyList.get(i).getStartBlockTime() == 0 && readyList.get(i).getBlockTime() != 0) {
System.out.println("进程" + readyList.get(i).getPid() + "开始阻塞,进入阻塞队列");
readyList.get(i).toBlock();
blockList.add(readyList.get(i));
readyList.remove(readyList.get(i));
i -= 1;
}
}
i += 1;
if (i >= readyList.size()) {
break;
}
}
}

if (blockList.size() > 0) {
int i = 0;
while (true) {
if (blockList.get(i).getBlockTime() == 0) {
System.out.println("进程" + blockList.get(i).getPid() + "阻塞结束,进入就绪队列");
blockList.get(i).toReady();
readyList.add(blockList.get(i));
blockList.remove(blockList.get(i));
pid = readyList.get(0).getPid();
i -= 1;
}
i += 1;
if (i >= blockList.size()) {
break;
}
}
}

if (readyList.size() > 0) { // 进程执行完毕则移出就绪队列
if (readyList.get(0).getAllTime() <= 0) {
readyList.get(0).toFinish();
System.out.println("进程" + readyList.get(0).getPid() + "执行完毕,周转时间: " +
(time - readyList.get(0).getArrTime() + 1) + ",状态:" + readyList.get(0).getState());
readyList.remove(readyList.get(0));
if (readyList.size() > 0) {
pid = readyList.get(0).getPid();
}
}
}

time += 1;
if (list.size() == 0 && readyList.size() == 0 && blockList.size() == 0) {
break;
}
}
return --time;
}

public static List<PCB> cloneList(List<PCB> list) {
List<PCB> listClone = new ArrayList<PCB>();
for (int i = 0; i < list.size(); i++) {
PCB pcb = list.get(i);
PCB pcbClone = new PCB(pcb.getPid(), pcb.getPriority(), pcb.getArrTime(), pcb.getAllTime(),
pcb.getCpuTime(), pcb.getStartBlockTime(), pcb.getBlockTime(), pcb.getState());
listClone.add(pcbClone);
}
return listClone;
}

public static void main(String[] args) {
while (true) {
System.out.println("请选择算法:---------------");
System.out.println("1、先来先服务");
System.out.println("2、抢占式短作业优先");
System.out.println("3、动态最高优先数优先");
System.out.println("4、比较上述三种算法");
System.out.println("------------------------");
Scanner reader = new Scanner(System.in);
System.out.print("请输入选项:");
int select = reader.nextInt();
switch (select) {
case 1:
List<PCB> list = init(4);
list.forEach(pcb -> {
pcb.show_SJF_FCFS();
});
FCFS(list);
break;
case 2:
List<PCB> list2 = init(4);
list2.forEach(pcb -> {
pcb.show_SJF_FCFS();
});
SJF(list2);
break;
case 3:
List<PCB> list3 = init(4);
list3.forEach(pcb -> {
pcb.show_HRRN();
});
HRRN(list3);
break;
case 4:
int time_FCFS = 0;
int time_SJF = 0;
int time_HRRN = 0;
List<PCB> list4 = init(4);
if (list4.size() > 0) {
List<PCB> list4_1 = cloneList(list4);
List<PCB> list4_2 = cloneList(list4);
List<PCB> list4_3 = cloneList(list4);
List<PCB> list4_all = cloneList(list4);
System.out.println("**************FCFS******************");
for (int i = 0; i < list4_1.size(); i++) {
list4_1.get(i).show_SJF_FCFS();
};
time_FCFS = FCFS(list4_1);
System.out.println("********************************");

System.out.println("****************SJF****************");
for (int i = 0; i < list4_2.size(); i++) {
list4_2.get(i).show_SJF_FCFS();
};
time_SJF = SJF(list4_2);
System.out.println("********************************");

System.out.println("*****************HRRN***************");
for (int i = 0; i < list4_3.size(); i++) {
list4_3.get(i).show_HRRN();
};
time_HRRN = HRRN(list4_3);
System.out.println("********************************");

System.out.println("=================情况综述======================");
System.out.println("=======进程情况========");
for (int i = 0; i < list4_all.size(); i++) {
list4_all.get(i).show_HRRN(); // 此方法的进程打印信息最全
};
System.out.println("FCFS 算法执行时间:" + time_FCFS);
System.out.println("SJF 算法执行时间:" + time_SJF);
System.out.println("HRRN 算法执行时间:" + time_HRRN);
System.out.println("=======================================");
}
break;
}
}
}
}