按优先数调度算法实现处理器调度。
在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。当就绪进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。
要求
原理
设计一个按优先数调度算法实现处理器调度的程序。
(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:
其中,进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。
指针——按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。
要求运行时间——假设进程需要运行的单位时间数。
优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。
状态——可假设有两种状态,“就绪”状态和“结束”状态。五个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。
(2) 在每次运行你所设计的处理器调度程序之前,为每个进程任意确定它的“优先数”和“要求运行时间”。
(3) 为了调度方便,把五个进程按给定的优先数从大到小连成队列。用一单元指出队首进程,用指针指出队列的连接情况。例:
(4) 处理器调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行一次优先数就减“1”。由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:
优先数-1
要求运行时间-1
来模拟进程的一次运行。
提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。
(5) 进程运行一次后,若要求运行时间¹0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它的状态修改成“结束”(E),且退出队列。
(6) 若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。
(7) 在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。
(8) 为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。
数据结构图
结构图可能比较长,大家可以看下面的原理。
原理
1、 首先定义进程PCB这个类,里面包含的属性有进程的名称、运行时间、优先级、还有状态
2、 定义运行类并继承线程类,里面包含的属性如下
use队列是用来存储所有的要运行的进程;
run队列是每运行一个进程,就把这个进程对象从use队列中拿出来放到run队列中,run队列相当于一个中间操作;
finish队列是每运行结束一个进程就放到finish队列中,当最后finish队列长度等于要运行的进程长度时就意味着所有的进程都运行完了。
3、 输入进程并加入到use队列中
4、 运行部分有点长主要看注释
因为要根据优先级比较大小,所以需要创建一个比较器
//利用比较器对use根据优先级pri进行从大到小排序
class PCBComparator implements Comparator<PCB> {
@Override
public int compare(PCB o1, PCB o2) {
int pri1 = o1.pri;
int pri2 = o2.pri;
return pri2 - pri1;
}
}
public void run(){
boolean flag = true;
if("第一个进程".equals(sign)){
count = 0;//时间片为0
Collections.sort(use,new PCBComparator());//第一次进程进入,时间片计数为0,然后对顺序表根据优先级进行排序
count++;//第一个时间片开始
while (flag){
if(run == null){//run中为空意味着此时没有进程运行
run.add(use.get(0));//将use里面的第一个,也就是优先级最高的放入
System.out.println("还没有进程被调度");
}
use.get(0).pri -= 1; //使加入到run中的进程优先级减1
use.get(0).workTime -= 1; // 使加入到run中的进程运行时间减1
use.get(0).state = "运行中";// 使加入到run中的进程状态改为运行中
//每个进程循环进行判断,如果运行时间为0后更改运行状态为finish
for (int i = 0; i < use.size(); ++i) {
if (use.get(i).workTime == 0) {
use.get(i).state = "运行结束";
}
}
System.out.println("经过了" + (count) + "个时间片后," + use.get(0).name + "被调用." + "还需" + use.get(0).workTime + "时间");
System.out.println("经过时间片数" + " " + "进程名字" + " " + "该进程优先级" + " " + "所需时间片数" + " 调度状态");
//打印未完成进程,use中就是还没有被运行的进程
for (int j = 0; j < use.size(); j++){
System.out.println(count + " " + use.get(j).name + " " + use.get(j).pri
+ " " + use.get(j).workTime + " " + use.get(j).state);
}
//打印已经完成的进程,finish中就是已经完成的进程
for (int j = 0; j < finish.size(); j++){
System.out
.println(count + " " + finish.get(j).name + " " + finish.get(j).pri
+ " " + finish.get(j).workTime + " " + finish.get(j).state);
}
Collections.sort(use,new PCBComparator());
count++;
//如果进程已经结束,则加入到finish,
for(int i = 0; i < use.size(); i++){
if(use.get(i).workTime == 0){
use.get(i).state = "运行结束";
finish.add(use.get(i));
use.remove(i);
}
}
//如果finish中放的进程等于一开始的进程数,说明进程全部执行完毕
if(finish.size() == num){
flag = false;
System.out.println("进程全部执行完毕!");
}
try{
sleep(1000);//间隔1000毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
总代码
import java.util.*;
class PCB {
public String name; //进程名称
public int workTime; //运行时间
public int pri; //优先级
public String state = "就绪"; //状态 R就绪 F完成
public PCB(String name, int workTime, int pri) {
this.name = name;
this.workTime = workTime;
this.pri = pri;
}
}
public class Process extends Thread {
private int num; //要运行的进程个数
private List<PCB> use = new ArrayList<>();//就绪的进程
private List<PCB> run = new ArrayList<>();//正在运行的进程
private List<PCB> finish = new ArrayList<>();//已经完成的进程
private int count; //记录时间片
private String sign;//标志第一次的运行
private void work(){
System.out.println("******************************************");
System.out.println("************* 优先级调度 ************");
//输入需要工作的进程
System.out.println("请输入进程个数(至少有1个进程)");
Scanner scan = new Scanner(System.in);
num = scan.nextInt();
for (int i = 1; i <= num; i++) {
System.out.println("请输入第" + i + "个进程名");
Scanner scan1 = new Scanner(System.in);
String name = scan1.next();
System.out.println("请输入第" + i + "个进程的优先级");
Scanner scan2 = new Scanner(System.in);
int pri = scan2.nextInt();
System.out.println("请输入第" + i + "个进程所需的运行时间");
Scanner scan3 = new Scanner(System.in);
int workTime = scan3.nextInt();
use.add(new PCB(name,workTime ,pri ));
System.out.println("");
}
sign = "第一个进程";
this.run();
}
//利用比较器对use根据优先级pri进行从大到小排序
class PCBComparator implements Comparator<PCB> {
@Override
public int compare(PCB o1, PCB o2) {
int pri1 = o1.pri;
int pri2 = o2.pri;
return pri2 - pri1;
}
}
public void run(){
boolean flag = true;
if("第一个进程".equals(sign)){
count = 0;//时间片为0
Collections.sort(use,new PCBComparator());//第一次进程进入,时间片计数为0,然后对顺序表根据优先级进行排序
count++;//第一个时间片开始
while (flag){
if(run == null){//run中为空意味着此时没有进程运行
run.add(use.get(0));//将use里面的第一个,也就是优先级最高的放入
System.out.println("还没有进程被调度");
}
use.get(0).pri -= 1; //使加入到run中的进程优先级减1
use.get(0).workTime -= 1; // 使加入到run中的进程运行时间减1
use.get(0).state = "运行中";// 使加入到run中的进程状态改为运行中
//每个进程循环进行判断,如果运行时间为0后更改运行状态为finish
for (int i = 0; i < use.size(); ++i) {
if (use.get(i).workTime == 0) {
use.get(i).state = "运行结束";
}
}
System.out.println("经过了" + (count) + "个时间片后," + use.get(0).name + "被调用." + "还需" + use.get(0).workTime + "时间");
System.out.println("经过时间片数" + " " + "进程名字" + " " + "该进程优先级" + " " + "所需时间片数" + " 调度状态");
//打印未完成进程,use中就是还没有被运行的进程
for (int j = 0; j < use.size(); j++){
System.out.println(count + " " + use.get(j).name + " " + use.get(j).pri
+ " " + use.get(j).workTime + " " + use.get(j).state);
}
//打印已经完成的进程,finish中就是已经完成的进程
for (int j = 0; j < finish.size(); j++){
System.out
.println(count + " " + finish.get(j).name + " " + finish.get(j).pri
+ " " + finish.get(j).workTime + " " + finish.get(j).state);
}
Collections.sort(use,new PCBComparator());
count++;
//如果进程已经结束,则加入到finish,
for(int i = 0; i < use.size(); i++){
if(use.get(i).workTime == 0){
use.get(i).state = "运行结束";
finish.add(use.get(i));
use.remove(i);
}
}
//如果finish中放的进程等于一开始的进程数,说明进程全部执行完毕
if(finish.size() == num){
flag = false;
System.out.println("进程全部执行完毕!");
}
try{
sleep(1000);//间隔1000毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Process process = new Process();
process.work();
}
}
测试结果