实验原题:
设计一个有 N个进程共行的进程调度程序。
进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。 进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间。进程的运行时间以时间片为单位进行计算。每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。
重复以上过程,直到所要进程都完成为止。
调度算法的流程图如下 :
java实现代码:
public class PCB {
private String name;//进程名
private String state;//状态
private Integer priority;//优先度
private Integer ntime;//需要运行时间
private Integer rtime;//到达时间
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Integer getPriority() {
return priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
public Integer getNtime() {
return ntime;
}
public void setNtime(Integer ntime) {
this.ntime = ntime;
}
public Integer getRtime() {
return rtime;
}
public void setRtime(Integer rtime) {
this.rtime = rtime;
}
public PCB(String name, String state, Integer priority, Integer ntime, Integer rtime) {
this.name = name;
this.state = state;
this.priority = priority;
this.ntime = ntime;
this.rtime = rtime;
}
public PCB() {
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Main {
static List<PCB> listOfProcess = new ArrayList();
public static void main(String[] args) {
System.out.println("**** 请输入进程号:");
//存入总进程数
Scanner s = new Scanner(System.in);
int num = s.nextInt();
//初始化进程信息,输入所有进程信息
input(num);
//显示所有进程
System.out.println("**** 当前就绪队列状态为:");
for (int i = 0; i < listOfProcess.size(); i++){
disp(listOfProcess.get(i));
}
System.out.println();
//初始时间
int h = 0;
while (listOfProcess.size() != 0){
h++;
System.out.println();
System.out.println("**** 当前时间是:"+h);
System.out.println();
listOfProcess.get(0).setState("run");
check(listOfProcess.get(0));
running(listOfProcess.get(0));
System.out.println("**** 输入任意值,并按回车键继续:");
s.next();
}
System.out.println("**** 进程已经完成.");
}
/* 建立进程就绪函数(进程运行时间到,置就绪状态*/
private static void running(PCB pcb) {
pcb.setRtime(pcb.getRtime()+1);
if (pcb.getRtime() == pcb.getNtime()){
destroy();
System.out.println(pcb.getName()+"以运行完成");
}else {
pcb.setPriority(pcb.getPriority()-1);
pcb.setState("wait");
sort(listOfProcess,0,listOfProcess.size()-1);
Collections.reverse(listOfProcess);
showWait();
}
}
/*建立进程撤消函数(进程运行结束,撤消进程)*/
private static void destroy() {
listOfProcess.remove(0);
}
/*建立就绪队列查看函数*/
private static void showWait(){
System.out.println("**** 运行完一个时间片之后,就绪队列为:");
for (int i = 0; i < listOfProcess.size(); i++){
disp(listOfProcess.get(i));
}
System.out.println();
}
/*建立对进程进行优先级排列函数*/
private static void sort(List<PCB> listOfProcess, int low, int high) {
/**
* 初始化start、end、key
* start为从前往后的游动下标
* end为从后往前的游动下标
* key是最开始的基准,在本轮递归中是不变的,变的是两个游标上的值
*/
int start = low;
int end = high;
int key = listOfProcess.get(low).getPriority();
/**
* 一切的一切,都是为了分治
* 一轮下来,找到当前队列的关键值,左边的值都比关键值小,右边的值都比关键值大
*/
while (end > start){
/**
* 从后到前
*
* 1、这里为什么还要判断end>start?
* 判断是否逼近结束。
* 啰嗦的解释:因为end不断在变,用于判断从后往前时是否到了与start最近处。
*
* 2、这里为什么判断listOfProcess.get(end).getPriority() >= key?
* 为了end从后往前逼近关键值。
* 是为了从后往前找到第一个比基准小的值,进行交换。确保本次从后往前排序的时候,以基准为标准,end游动下标后面的值比基准大
*/
while (end > start && listOfProcess.get(end).getPriority() >= key){
end--;
}
//start与end值交换,把基准值换到end位置上,此时,end是从end开始往后的队列中,值最小的
if (listOfProcess.get(end).getPriority() <= key){
PCB temp = listOfProcess.get(end);
listOfProcess.set(end, listOfProcess.get(start));
listOfProcess.set(start, temp);
}
//从前往后,道理一样,从前开始保证,start前的都比start小
while (end > start && listOfProcess.get(start).getPriority() <= key){
start++;
}
//start与end值交换,把基准值换到start位置上,此时,start是从start开始往前的队列中,值最大的
if (listOfProcess.get(start).getPriority() >= key){
PCB temp = listOfProcess.get(end);
listOfProcess.set(end, listOfProcess.get(start));
listOfProcess.set(start, temp);
}
}
/**
* 以上是为了找到关键值,接下来的递归才是重中之重
*
* 1、为什么要判断low < start、high > end?
* 因为,当start没有改变时,说明这一段已经排序ok,无需接着往下递归了
*
* 2、start为什么-1,end为什么+1?
* start和end若不重合,两者已经排序好了
* 若重合,则这个重合的地方已经确定排序
*
*/
if (low < start){
sort(listOfProcess, low, start-1);
}
if (high > end){
sort(listOfProcess, end+1, high);
}
}
/*建立进程查看函数*/
private static void check(PCB pcb){
//显示正在运行的进程
System.out.println("**** 当前正在运行的进程是:"+pcb.getName());
disp(pcb);
//显示就绪进程
System.out.println("**** 当前就绪队列状态为:");
for (int i = 1; i < listOfProcess.size(); i++){
disp(listOfProcess.get(i));
}
System.out.println();
}
/*建立进程显示函数,用于显示当前进程*/
private static void disp(PCB pcb) {
System.out.println("qname \t state \t super \t ndtime \t runtime");
System.out.println(pcb.getName()+" \t "+ pcb.getState()+" \t "+pcb.getPriority()+" \t\t "+pcb.getNtime()+" \t\t\t "+pcb.getRtime());
}
/*建立进程控制块函数*/
private static void input(int num) {
Scanner s = new Scanner(System.in);
//填充列表
for (int i = 0; i < num; i++){
System.out.println("输入进程名:");
String name = s.next();
System.out.println("输入进程优先数:");
int priority = s.nextInt();
System.out.println("输入进程运行时间:");
int ntime = s.nextInt();
System.out.println();
//初始化当前进程的PCB
PCB pcb = new PCB(name,"wait",priority,ntime,0);
//加入队列
listOfProcess.add(pcb);
}
// PCB pcb1 = new PCB("pcb1","wait",4,2,0);
// PCB pcb2 = new PCB("pcb2","wait",5,3,0);
// PCB pcb3 = new PCB("pcb3","wait",1,1,0);
// PCB pcb4 = new PCB("pcb4","wait",3,2,0);
// PCB pcb5 = new PCB("pcb5","wait",2,1,0);
// listOfProcess.add(pcb1);
// listOfProcess.add(pcb2);
// listOfProcess.add(pcb3);
// listOfProcess.add(pcb4);
// listOfProcess.add(pcb5);
//建立对进程进行优先级排列函数
sort(listOfProcess, 0, (listOfProcess.size()-1));
Collections.reverse(listOfProcess);
}
}