Java实现处理器调度
设计一个按优先数调度算法实现处理器调度的程序。
(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:
进程名 | 作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。 |
---|---|
指针 | 按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。 |
要求运行时间 | 假设进程需要运行的单位时间数。 |
优先数 | 赋予进程的优先数,调度时总是选取优先数大的进程先执行。 |
状态 | 可假设有两种状态,“就绪”状态和“结束”状态。五个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。 |
(2) 在每次运行你所设计的处理器调度程序之前,为每个进程任意确定它的“优先数”和“要求运行时间”。
所以我们可以写一个基础类PCB来保存这五个属性,但由于Java中没有指针,所以使用链表中的节点来代替指针的功能:
package cn.OS;
/**
* @author LuoSheng
* @创建时间 2020/11/5
* @描述 进程控制块PCB
*/
public class PCB {
/**
* 进程名
*/
public String pcbName;
/**
* 设置节点
*/
public PCB next;
/**
* 运行时间
*/
public int time;
/**
* 优先级
*/
public int priority;
/**
* 状态
*/
public char state = 'R';
public PCB(String pcbName, int time, int priority) {
this.pcbName = pcbName;
this.time = time;
this.priority = priority;
}
@Override
public String toString() {
if (next == null) {
return "进程名:" +pcbName +" next:"+null+ " 要求运行时间:" + time + " 优先级数:" + priority
+ " 状态:" + state;
}else{
return "进程名:" + pcbName +" next:"+next.pcbName+ " 要求运行时间:" + time + " 优先级数:" + priority
+ " 状态:" + state;
}
}
}
(3) 为了调度方便,把五个进程按给定的优先数从大到小连成队列。用一单元指出队首进程,用指针指出队列的连接情况。例:
此处,我使用的是next代替指针指向下一个节点。
(4) 处理器调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行一次优先数就减“1”。由于本实习是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:
优先数-1
要求运行时间-1
来模拟进程的一次运行。
提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。
(5) 进程运行一次后,若要求运行时间!=0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它的状态修改成“结束”(E),且退出队列。
(6) 若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。
(7) 在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。
(8) 为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。
根据上述要求可对集合进行如下操作。
- 进程功能实现代码:
package cn.OS;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* @author LuoSheng
* @创建时间 2020/11/5
* @描述 util工具类 实现进程插入链表和进程的运行方法
*/
public class Util {
/**
* PCB进程块运行方法
*/
public void runPCB(ArrayList<PCB> pcbs) {
cut();
System.out.println("==============优先数调度算法处理器调度已开启==============");
cut();
reoder(pcbs);
display(pcbs);
cut();
for (int i = 0; i < pcbs.size(); i++) {
System.out.println();
System.out.println("开始执行" + pcbs.get(i).pcbName + "进程");
System.out.println(pcbs.get(i));
pcbs.get(i).priority -= 1;
pcbs.get(i).time -= 1;
if (pcbs.get(i).time == 0) {
pcbs.get(i).state = 'E';
System.out.println(pcbs.get(i).pcbName + "退出进程队列,信息如下:");
System.out.println(pcbs.get(i));
pcbs.remove(i);
} else {
System.out.println(pcbs.get(i).pcbName + "进程执行完毕,信息如下:");
System.out.println(pcbs.get(i));
reoder(pcbs);
}
if (pcbs == null) {
System.out.println("所有进程执行完毕!");
} else {
System.out.println("此时进程队列的所有进程信息:");
cut();
display(pcbs);
cut();
}
i -= 1;
}
}
/**
* 根据优先级进行降序排序
*/
public void reoder(ArrayList<PCB> pcbs) {
Collections.sort(pcbs, new Comparator<PCB>() {
@Override
public int compare(PCB o1, PCB o2) {
int temp = o1.priority - o2.priority;
if (temp < 0) {
return 1;
}
if (temp > 0) {
return -1;
}
return 0;
}
});
}
/**
* 遍历进程
*/
public void display(ArrayList<PCB> pcbs) {
for (PCB p :
pcbs) {
System.out.println(p);
}
}
/**
* 分割线
*/
public void cut() {
System.out.println("======================================================");
}
}
在测试类中我先将数据添加到集合中,再把集合中的数据添加到链表中,相对于数组储存数据,使用集合可以添加任意个数的对象,具体实现代码如下:
public class Test {
public static void main(String[] args) {
ArrayList<PCB> pcbs = new ArrayList<>();
pcbs.add(new PCB("P1", 2, 2));
pcbs.add(new PCB("P2", 2, 2));
pcbs.add(new PCB("P3", 5, 3));
pcbs.add(new PCB("P4", 2, 1));
Util util = new Util();
// 执行处理器调度
util.runPCB(pcbs);
}
}