java模拟实现操作系统进程调度中的多级反馈队列算法
操作系统学了一学期了,期末作业布置下来,用编程语言模拟进程调度的过程,只会java,于是就写了一下,通过控制台模拟,模拟过程看起来可能十分不直观。试了几个例子,发现没有错误。
注释很详细,直接粘上代码
代码
MainTest.java 主方法
package 多级反馈队列算法;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
public class MainTest {
public static void main(String[] args) {
LevelQueue<Process> Level1Queue = new LevelQueue<Process>(1, 1); // 一级队列,轮转时间片为1
LevelQueue<Process> Level2Queue = new LevelQueue<Process>(2, 2); // 二级队列,轮转时间片为2
LevelQueue<Process> Level3Queue = new LevelQueue<Process>(3, 4); // 三级队列,轮转时间片为4
LevelQueue<Process> Level4Queue = new LevelQueue<Process>(4, 999); // 四级队列,轮转时间片为999(认为是无限大)
List<Process> processes = new ArrayList<Process>(); // 存储初始化准备进程的ArrayList
int[] arrivalTime; // 进程到达时间数组
int currentTime = 0; // 存储当前时间
int processSum; // 总进程数
int processRemaining; // 剩余进程数
// 初始化进程信息
Scanner sc = new Scanner(System.in);
System.out.println("先输入总进程数, 再依次输入各个进程的到达时间和服务时间");
processSum = sc.nextInt();
processRemaining = processSum;
arrivalTime = new int[processSum];// 初始化到达时间数组
for (int i = 0; i < processSum; i++) {
int a = sc.nextInt(); // 到达时间
int s = sc.nextInt(); // 服务时间
Process p = new Process("P" + i, a, s);
arrivalTime[i] = a;
processes.add(p);
}
sc.close();
// //返回当前用户输入的数据
// Iterator it = processes.iterator();
// while (it.hasNext()){
// Process p = (Process)it.next();
// System.out.println(p.toString());
// }
Process.ifAllCompleted(); // 输出当前进程数
// 将进程按照到达时间顺序进行排序 并获得到达时间数组
for (int i = 0; i < processSum; i++) {
for (int j = i + 1; j < processSum; j++) {
Process p1 = (Process) processes.get(i);
Process p2 = (Process) processes.get(j);
if (p2.arrivalTime < p1.arrivalTime) {
processes.set(i, p2);
processes.set(j, p1);
arrivalTime[i] = p2.arrivalTime;
arrivalTime[j] = p1.arrivalTime;
} else if (p2.arrivalTime == p1.arrivalTime) { // 若同时到达 则短作业优先
if (p2.serviceTime < p1.serviceTime) {
processes.set(i, p2);
processes.set(j, p1);
arrivalTime[i] = p2.arrivalTime;
arrivalTime[j] = p1.arrivalTime;
} else if (p2.serviceTime == p1.serviceTime) { // 若服务时间也相等,则将p2放在p1后面,并将p1后面的进程和p2交换
Process tmp = (Process) processes.get(i + 1);
processes.set(i + 1, p2);
processes.set(j, tmp);
arrivalTime[i + 1] = p2.arrivalTime;
arrivalTime[j] = tmp.arrivalTime;
}
}
}
}
// 验证 排序是否正确
Iterator<Process> it2 = processes.iterator();
while (it2.hasNext()) {
Process p = (Process) it2.next();
System.out.println(p.toString());
}
for (int i = 0; i < arrivalTime.length; i++) {
System.out.println(arrivalTime[i]);
}
// 开始模拟运行
int position = 0;// 记录当前运行的进程位置,从0第一个进程开始
while (true) {
// 首先判断是否有新的作业到达
if (position < processSum) { // 若大于等于进程总数则证明全部入队
if (arrivalTime[position] <= currentTime) { // 取出数组第一个进程的到达时间与当前时间进行比较
// ,若等于或者小于当前时间,
// 说明有程序到达并进入第一队列
Process p = (Process) processes.get(position);
Level1Queue.add(p); // 进程入一级队列
System.out.println(p.name + "进程于" + p.arrivalTime + "时间,加入一级队列");
if (position == 0) { // 若是第一个到达并开始的作业,则更新当前时间为其到达时间
currentTime = p.arrivalTime;
}
System.out.println("当前时间:" + currentTime);
p.queue = Level1Queue; // 为进程初始化当前所在队列信息
position++;
}
} else {
if (Process.ifAllCompleted()) { // 如果所有进程完毕则退出循环
break;
}
}
if (!Level1Queue.isEmpty()) // 若一级队列非空,则优先执行一级队列
{
Process p = Level1Queue.peek();
if (p.serviceTime <= Level1Queue.timeSlice) { // 如果队头进程服务时间小于等于该队列时间片。
// 则进程完成
p.Finished(); // 进程结束 并自动出队
processRemaining -= 1; // 进程总数-1
} else {
// 一级出队并打入下一级队列
Level1Queue.poll();
p.excutedTime += Level1Queue.timeSlice; // 更新进程的运行时间
p.queue = Level2Queue; // 为进程更新当前所在队列信息
Level2Queue.add(p); // 进入二级队列
}
// 更新时间 判断是否完成所有进程
currentTime += Level1Queue.timeSlice; // 当前时间等于执行前时间加上当前队列时间片
System.out.println("当前时间:" + currentTime);
if (Process.ifAllCompleted()) { // 如果所有进程完毕则退出循环
break;
}
} else if (!Level2Queue.isEmpty()) // 若一级队列为空,二级队列非空,则优先执行二级队列
{
Process p = Level2Queue.peek();
int timeRemaining = p.serviceTime - p.excutedTime; // 进程剩余时间
if (timeRemaining <= Level2Queue.timeSlice) { // 如果队头进程服务时间小于等于该队列时间片。
// 则进程完成
p.Finished(); // 进程结束 并自动出队
processRemaining -= 1; // 进程总数-1
// 更新时间 判断是否完成所有进程
currentTime += timeRemaining; // 当前时间等于执行前时间加上当前队列时间片
System.out.println("当前时间:" + currentTime);
if (Process.ifAllCompleted()) { // 如果所有进程完毕则退出循环
break;
}
} else {
// 二级出队并打入下一级队列
Level2Queue.poll();
p.excutedTime += Level2Queue.timeSlice; // 更新进程的运行时间
p.queue = Level3Queue; // 为进程更新当前所在队列信息
Level3Queue.add(p); // 进入三级队列
// 更新时间 判断是否完成所有进程
currentTime += Level2Queue.timeSlice; // 当前时间等于执行前时间加上当前队列时间片
System.out.println("当前时间:" + currentTime);
if (Process.ifAllCompleted()) { // 如果所有进程完毕则退出循环
break;
}
}
} else if (!Level3Queue.isEmpty()) // 若二级队列为空,执行三级队列
{
Process p = Level3Queue.peek();
int timeRemaining = p.serviceTime - p.excutedTime; // 进程剩余时间
if (timeRemaining <= Level3Queue.timeSlice) { // 如果队头进程服务时间小于等于该队列时间片。
// 则进程完成
p.Finished(); // 进程结束 并自动出队
processRemaining -= 1; // 进程总数-1
// 更新时间 判断是否完成所有进程
currentTime += timeRemaining; // 当前时间等于执行前时间加上当前队列时间片
System.out.println("当前时间:" + currentTime);
if (Process.ifAllCompleted()) { // 如果所有进程完毕则退出循环
break;
}
} else {
// 三级出队并打入下一级队列
Level3Queue.poll();
p.excutedTime += Level3Queue.timeSlice; // 更新进程的运行时间
p.queue = Level4Queue; // 为进程更新当前所在队列信息
Level4Queue.add(p); // 进入三级队列
// 更新时间 判断是否完成所有进程
currentTime += Level3Queue.timeSlice; // 当前时间等于执行前时间加上当前队列时间片
System.out.println("当前时间:" + currentTime);
if (Process.ifAllCompleted()) { // 如果所有进程完毕则退出循环
break;
}
}
} else if (!Level4Queue.isEmpty()) { // 最后执行四级队列
Process p = Level4Queue.peek();
int timeRemaining = p.serviceTime - p.excutedTime; // 进程剩余时间
Process.ifAllCompleted();
p.Finished(); // 进程结束 并自动出队
processRemaining -= 1; // 进程总数-1
currentTime += timeRemaining; // 当前时间等于执行前时间加上当前队列时间片
System.out.println("当前时间:" + currentTime);
if (Process.ifAllCompleted()) { // 如果所有进程完毕则退出循环
break;
}
}
System.out.println(processRemaining);
}
}
}
LevelQueue.java 等级队列类
package 多级反馈队列算法;
public class LevelQueue<T> implements Queue<Process> {
protected Node<Process> front, rear;// front 和rear 分别指向队头和队尾节点
protected int levelOfQueue; // 队列等级 1,2,3
protected int timeSlice; // 队列时间片 1,2,4
protected int account = 0; // 队列中排队的进程数
public LevelQueue(int levelOfQueue, int timeSlice) { // 构造队列
super();
this.levelOfQueue = levelOfQueue;
this.timeSlice = timeSlice;
}
@Override
public boolean isEmpty() { // 判断队列是否为空 若为空返回true
// TODO Auto-generated method stub
if (this.front == null && this.rear == null) {
System.out.println(this.levelOfQueue + "级队列当前没有进程正在运行");
return true;
} else {
System.out.println(this.levelOfQueue + "级队列当前有" + this.account + "个进程正在运行");
return false;
}
}
@Override
public boolean add(Process x) // 入队操作
{
// TODO Auto-generated method stub
if (x == null) {
return false; // 元素x 入队 空对象不能入队
}
// 进程到达cpu
Node<Process> q = new Node<Process>(x, null); // 局部变量q接收数据内容。
if (this.front == null) {
this.front = q; // 空队插入
account++;
} else {
this.rear.next = q; // 队列尾插入
account++;
}
this.rear = q; // 尾指针位置更新
return true; // 插入成功
}
@Override // 返回队头操作
public Process peek() {
// TODO Auto-generated method stub
// 只返回队头元素,不进行任何操作,若队列为空则返回null;
return this.isEmpty() ? null : this.front.data;
}
@Override
public Process poll() { // 出队操作 返回队头元素,若队列为空返回 null
// TODO Auto-generated method stub
if (isEmpty()) {
return null;
}
Process x = this.front.data; // 取得队头元素
this.front = this.front.next; // 删除队头元素
if (this.front == null) {
this.rear = null;
}
account--;
return x;
}
}
Node.java 队列节点类
package 多级反馈队列算法;
public class Node<T> // 链式队列节点类
{
public Process data; // 数据域 存储数据元素
public Node<Process> next; // 地址域,引用后继节点
public Node(Process data, Node<Process> next) {
super();
this.data = data;
this.next = next;
}
public Node() {
super();
}
/*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
// TODO Auto-generated method stub
return this.data.toString();
}
}
Process.java 进程类
package 多级反馈队列算法;
public class Process // 进程类
{
static int amountOfProcess = 0; // 所有进程总数
protected String name; // 进程名
protected int arrivalTime; // 进程到达内存的时间
protected int serviceTime; // 进程完成需要占用cpu的服务时间
protected int excutedTime = 0; // 进程已经执行时间
protected LevelQueue<Process> queue = null; // 当前进程所在队列
public Process(String name, int arrivalTime, int serviceTime) {
super();
this.name = name;
this.arrivalTime = arrivalTime;
this.serviceTime = serviceTime;
amountOfProcess += 1;// 每创建一个进程对象,进程总数+1
}
public void Finished() { // 进程结束
// 执行出队操作
queue.poll();
System.out.println("-------------------");
System.out.println("进程:" + this.name + "执行完毕,结束时位于第" + this.queue.levelOfQueue + "队列。");
System.out.println(this.toString());
amountOfProcess -= 1;// 每完成一个进程对象,进程总数-1
}
@Override
public String toString() {
// TODO Auto-generated method stub
if (queue != null) {
return "进程:" + this.name + ",到达时间:" + this.arrivalTime + ",服务时间" + this.serviceTime + ",进程已经执行时间:"
+ this.excutedTime + ",进程当前所在队列" + queue.levelOfQueue + "。";
} else {
return "进程:" + this.name + ",到达时间:" + this.arrivalTime + ",服务时间" + this.serviceTime;
}
}
public static boolean ifAllCompleted() {
if (amountOfProcess == 0) {
System.out.println("当前没有进程正在运行");
return true;
} else {
System.out.println("当前有" + amountOfProcess + "个进程等待运行。");
return false;
}
}
}
Queue.java
package 多级反馈队列算法;
public interface Queue<T> //队列接口类
{
public abstract boolean isEmpty();
public abstract boolean add(T x);//添加成功返回true
public abstract T peek(); //返回队头元素,若为空返回null
public abstract T poll(); // 出队,并返回队头元素,若为空返回null
}