多级反馈队列

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

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

运行结果:

相关推荐
RTC老炮7 分钟前
webrtc弱网-ReceiveSideCongestionController类源码分析及算法原理
网络·算法·webrtc
21号 19 分钟前
9.Redis 集群(重在理解)
数据库·redis·算法
Chen-Edward16 分钟前
有了Spring为什么还有要Spring Boot?
java·spring boot·spring
magic3341656335 分钟前
Springboot整合MinIO文件服务(windows版本)
windows·spring boot·后端·minio·文件对象存储
陈小桔1 小时前
idea中重新加载所有maven项目失败,但maven compile成功
java·maven
小学鸡!1 小时前
Spring Boot实现日志链路追踪
java·spring boot·后端
xiaogg36781 小时前
阿里云k8s1.33部署yaml和dockerfile配置文件
java·linux·kubernetes
逆光的July2 小时前
Hikari连接池
java
微风粼粼2 小时前
eclipse 导入javaweb项目,以及配置教程(傻瓜式教学)
java·ide·eclipse
番茄Salad2 小时前
Spring Boot临时解决循环依赖注入问题
java·spring boot·spring cloud