Bootstrap

多级反馈队列

多级反馈队列调度算法的调度机制可描述如下:

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();
    }
}

运行结果:

;