多级反馈队列调度算法的调度机制可描述如下:
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(); } }