多级反馈队列调度算法的调度机制可描述如下:
1).设置多个就绪队列。
(2) 每个队列都采用FCFS算法。当新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可撤离系统。否则,即它在一个时间片结束时尚未完成,调度程序将其转入第二队列的末尾等待调度;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,......,依此类推。当进程最后被降到第n队列后,在第n队列中便采取按RR方式运行。
(3) 按队列优先级调度。调度程序首先调度最高优先级队列中的诸进程运行,仅当第一队列空闲时才调度第二队列中的进程运行;换言之,仅当第1~(i-1)所有队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时又有新进程进入任一优先级较高的队列,此时须立即把正在运行的进程放回到第i队列的末尾,而把处理机分配给新到的高优先级进程。
代码:
import java.util.LinkedList;
import java.util.Scanner;
public class MultiLevelFeedbackQueueScheduler1 {
static final int time_slice = 1; // 第一队列时间片长度(分钟)
static final int N = 4; // 进程数
static class PCB {
String process_name; // 进程名字
int arrive_time; // 到达时间(分钟)
int service_time; // 需要服务时间(分钟)
int remain_time; // 还差多少时间(分钟)
int complete_time; // 完成时间(分钟)
char state; // 进程状态
public PCB(String process_name, int arrive_time, int service_time) {
this.process_name = process_name;
this.arrive_time = arrive_time;
this.service_time = service_time;
this.remain_time = service_time;
this.complete_time = 0;
this.state = 'w';
}
}
static LinkedList<PCB> Coming_queue = new LinkedList<>(); // 未到达队列
static LinkedList<PCB> Finish_queue = new LinkedList<>(); // 已完成队列
static LinkedList<PCB>[] Wait_queue; // 反馈队列
static int[] Queue_time_slice; // 各反馈队列的时间片(分钟)
static int Queue_Num; // 反馈队列数量
public static void sort(LinkedList<PCB> list) {
list.sort((p1, p2) -> Integer.compare(p1.arrive_time, p2.arrive_time));//按照到达的时间进行排序
}
public static void init_wait_queue(int queue_num) {
Queue_time_slice = new int[queue_num];
Wait_queue = (LinkedList<PCB>[]) new LinkedList<?>[queue_num]; // 泛型数组初始化
for (int i = 0; i < queue_num; i++) {
Queue_time_slice[i] = (int) (time_slice * Math.pow(2, i));
Wait_queue[i] = new LinkedList<>();
}
}
public static int input() {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入反馈队列级数: ");
Queue_Num = scanner.nextInt();
LinkedList<PCB> pcbList = new LinkedList<>();
for (int i = 0; i < N; i++) {
System.out.println("------\n请输入第" + (i + 1) + "进程名字: ");
String name = scanner.next();
System.out.print("请输入到达时间 (格式 HH:mm): ");
String timeStr = scanner.next();
String[] timeParts = timeStr.split(":");//按照:进行分割
int hours = Integer.parseInt(timeParts[0]);//integer.parseint()是将整型数据Integer转换为基本数据类型int
int minutes = Integer.parseInt(timeParts[1]);
int arriveTime = hours * 60 + minutes; // 转换为分钟
System.out.print("请输入服务时间 (分钟): ");
int serviceTime = scanner.nextInt();
pcbList.add(new PCB(name, arriveTime, serviceTime));
}
sort(pcbList);
for (PCB pcb : pcbList) {
Coming_queue.add(pcb);
}
init_wait_queue(Queue_Num);
return 0;
}
public static boolean accept_process(int current_time) {
while (!Coming_queue.isEmpty() && Coming_queue.peek().arrive_time <= current_time) {
Wait_queue[0].add(Coming_queue.poll());
return true;
}
return false;
}
public static void run() {
boolean over = false;
int current_time = Coming_queue.peek().arrive_time; // 系统当前时间(分钟)
PCB temp = null; // 存放要执行进程的pcb
int t = 0; // 存放时间片(分钟)
int queue_serial = 0; // 要执行进程所在队列号,从0~Queue_Num-1
int count = 1; // 调度次数
while (true) {
over = true;
accept_process(current_time); // 接收当前时间到达的进程
for (int i = 0; i < Queue_Num; i++) {
if (!Wait_queue[i].isEmpty()) {
over = false;
temp = Wait_queue[i].poll();
t = Queue_time_slice[i];
queue_serial = i;
break;
}
}
if (!Coming_queue.isEmpty()) {
over = false;
}
if (over) {
break;
}
System.out.println("\n第" + count + "次调度进程: " + temp.process_name + " 时间 : " + formatTime(current_time));
while (true) {
t--;
current_time++;
temp.state = 'r';
temp.remain_time--;
if (temp.remain_time == 0) { // 进程执行完
temp.state = 'f';
temp.complete_time = current_time;
Finish_queue.add(temp);
break;
} else if (t == 0) { // 进程还没执行完但是时间片用完
temp.state = 'w';
if (queue_serial == Queue_Num - 1) {
Wait_queue[queue_serial].add(temp); // 插入最后一级队尾
} else {
Wait_queue[queue_serial + 1].add(temp); // 插入下一级反馈队列
}
break;
} else if (queue_serial != 0 && accept_process(current_time)) { // 进程还没执行完,时间片还没用完,可以被抢占
temp.state = 'w';
Wait_queue[queue_serial].add(temp); // 插入本级反馈队列
break;
}
}
count++;
}
}
public static void print() {
float[] round_time = new float[N]; // 周转时间
float[] force_round_time = new float[N]; // 带权周转时间
float sum = 0; // 存放各进程的带权周转时间和
System.out.println("\n 进程 |" + "到达时间 |" + " 服务时间 |" + " 完成时间 |" + " 周转时间 |" + " 带权周转时间");
int i = 0;
while (!Finish_queue.isEmpty()) {
PCB pcb = Finish_queue.poll();
round_time[i] = pcb.complete_time - pcb.arrive_time;
force_round_time[i] = round_time[i] / pcb.service_time;
System.out.printf("%s\t| %s\t | %d \t | %s\t | %.2f\t | %.2f\n",
pcb.process_name, formatTime(pcb.arrive_time), pcb.service_time, formatTime(pcb.complete_time),
round_time[i], force_round_time[i]);
sum += force_round_time[i];
i++;
}
System.out.printf("\n\n系统平均带权周转时间: %.2f\n", sum / i);
}
public static String formatTime(int minutes) {
int hours = minutes / 60;
int mins = minutes % 60;
return String.format("%02d:%02d", hours, mins);
}
public static void main(String[] args) {
System.out.println("\t\t多级反馈队列调度算法");
input();
run();
print();
}
}