RR 时间片轮转算法 (java)

操作系统中的 时间片算法

  • 运行结果
    在这里插入图片描述
    在这里插入图片描述
  • 流程图

在这里插入图片描述

---------------------java代码------------------------

package operate;

import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

/**
 * 时间片轮转调度算法
 * 抢占式, 单CPU
 * @author ymj
 * @Date: 2019/12/15 23:13
 */
public class RR {
    static Scanner cin = new Scanner(System.in);

    /** 进程控制块 */
    static class PCB implements Comparable<PCB>{
        int id; // 进程id
        int arriveTime; // 到达时间
        int runTime; // 运行时间
        int hasRanTime = 0; // 已经运行时间, 初始值为0

        int turnAroundTime; // 周转时间
        int waitTime; // 等待时间

        int responseTime;// 响应时间 == 首次运行时间-到达时间
        PCB(int id, int arriveTime, int runTime){
            this.id = id;
            this.arriveTime = arriveTime;
            this.runTime = runTime;
        }

        @Override
        public int compareTo(PCB o) { // 按照 到达时间 进入就绪队列
            return  this.arriveTime - o.arriveTime;
        }
    }

    static PCB[] pcbs; // 进程数组
    static int timeSlice; // 时间片
    /** 进程到达队列 */
    static Queue<PCB> queue = new PriorityQueue<>();

    /** 初始化 PCB 信息 */
    static void initPCB(){
        System.out.print("输入进程数: ");
        int num = cin.nextInt();
        pcbs = new PCB[num+1];
        System.out.println("输入到达时间, 运行时间");
        for(int i = 1; i <= num; i++) {
            System.out.print("进程" + i + ":");
            pcbs[i] = new PCB(i, cin.nextInt(), cin.nextInt());
            queue.offer(pcbs[i]);
        }
        System.out.print("输入时间片大小:");
        timeSlice = cin.nextInt();
    }

    /** 判断当前已经到达的进程, 并使之进入就绪队列 */
    static boolean judge(Queue<PCB> readyQueue, int currentTime){
        boolean flag = false; // 为 true 表示 有 到达的进程
        while (true){
            PCB pcb = queue.peek(); // 最先到达的进程
            if (pcb == null){ // 所有进程都已经进入了就绪队列
                break;
            }else if(pcb.arriveTime <= currentTime){ // 当前有进程到达
                PCB runPCB = queue.poll();
                readyQueue.offer(runPCB); // 进入就绪队列等待运行
                flag = true;
            }else { // 当前没有进程到达
                break;
            }
        }
        return flag;
    }

    /** 进程进入处理机运行, 如果进程运行完成返回 true*/
    static boolean processRun(PCB pcb, int currentTime){
        if(pcb.hasRanTime == 0){ // 进程首次运行时间
            pcb.responseTime = currentTime;
        }
        pcb.hasRanTime++; // 进入 处理机运行
        System.out.printf("  %d\n", pcb.id);
        if(pcb.hasRanTime == pcb.runTime){ // 进程已经结束
            pcb.turnAroundTime = currentTime+1 - pcb.arriveTime;  // 周转时间
            pcb.waitTime = pcb.turnAroundTime - pcb.runTime; // 等待时间
            pcb.responseTime -= pcb.arriveTime;
            return true;
        }else {
            return false;
        }
    }

    /** 处理机运行 */
    static void run() {
        int currentTime = 0; // 当前时间
        if(!queue.isEmpty()){
            currentTime = queue.peek().arriveTime;
        }
        /** 定义就绪队列 */
        Queue<PCB> readyQueue = new LinkedList<>();
        int timeSliceFlag = timeSlice; // 时间片标记 (假设 刚开始 是一个时间片的开始)
        PCB runPcb = null;
        System.out.println("now   正在运行的进程");
        while (true) {
            System.out.printf("%d\t ", currentTime);
            if(queue.isEmpty() && readyQueue.isEmpty() && runPcb== null){
                System.out.println("当前所有进程运行结束");
                break;
            }else{ // 进程进入 处理机运行
                /** 判断是否到一个时间片 */
                if(timeSliceFlag % timeSlice == 0){ // 一个时间片到
                    /** 判断当前已经到达的进程, 并使之进入就绪队列 */
                    judge(readyQueue, currentTime);
                    if(runPcb != null){ // 处理机上还有进程
                        // 此时要下处理机, 进入就绪队列
                        readyQueue.offer(runPcb);
                        runPcb = null; // 此时处理机空闲
                    }
                    runPcb = readyQueue.poll(); // 出就绪队列,
                    if(runPcb == null){ // 就绪队列为空, 意味着此时处理机空闲,而且没有到达的进程
                        currentTime++; // 处理机等待
                        System.out.printf("  处理机空闲,\n");
                        continue; // 进入下一轮
                    }
                }
                /** 在 处理机中 运行 进程-->runPCB*/
                if(processRun(runPcb, currentTime) == true){ // 运行后 进程已经结束
                    runPcb = null;
                    timeSliceFlag = timeSlice; // 重新开始一个新的时间片
                }else { // 进程没有结束
                    timeSliceFlag++;
                }

                /** 时间片+1 */
                currentTime++;

            }
        }
    }

    public static void main(String[] args) {
        initPCB();
        System.out.println("-----处理机开始运行-----");
        run();
        System.out.println("-----处理机运行结束-----");
        showTurnAroundTime();
    }

    // 周转时间
    private static void showTurnAroundTime() {
        double averageT = 0;
        double averageWTAT = 0;
        double averageWT = 0;
        System.out.println("进程\t 周转时间\t 带权周转时间\t 等待时间\t 响应时间\t");
        for (int i = 1; i < pcbs.length; i ++) {
            int turnAroundTime = pcbs[i].turnAroundTime;
            double weightTurnAroundTime = turnAroundTime*1.0/pcbs[i].runTime;
            int waitTime = pcbs[i].waitTime;
            int responseTime = pcbs[i].responseTime;
            System.out.printf("%d\t     %d\t\t\t  %.2f\t\t\t %d\t\t\t %d\n" ,i , turnAroundTime,  weightTurnAroundTime, waitTime, responseTime);
            averageT += turnAroundTime;
            averageWTAT += weightTurnAroundTime;
            averageWT += waitTime;
        }
        averageT /= pcbs.length-1;
        averageWTAT /= pcbs.length-1;
        averageWT /= pcbs.length-1;
        System.out.println("平均周转时间:" + averageT);
        System.out.printf("平均带权周转时间:%.2f\n", averageWTAT);
        System.out.println("平均等待时间:" + averageWT);
    }
}


  • 14
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
时间片轮转调度算法是一种常见的进程调度算法,它是一种基于时间片的调度算法,可以保证每个进程都能够公平地使用CPU。在Java中,可以通过以下方式实现时间片轮转调度算法: ```java import java.util.LinkedList; import java.util.Queue; public class RoundRobin { public static void main(String[] args) { int[] process = {1, 2, 3, 4, 5}; int[] arrivalTime = {0, 1, 2, 3, 4}; int[] burstTime = {5, 3, 8, 6, 4}; int quantum = 3; roundRobin(process, arrivalTime, burstTime, quantum); } public static void roundRobin(int[] process, int[] arrivalTime, int[] burstTime, int quantum) { Queue<Integer> queue = new LinkedList<>(); int n = process.length; int[] remainingTime = new int[n]; int[] waitingTime = new int[n]; int[] turnaroundTime = new int[n]; int totalWaitingTime = 0; int totalTurnaroundTime = 0; for (int i = 0; i < n; i++) { remainingTime[i] = burstTime[i]; } int time = 0; queue.add(0); while (!queue.isEmpty()) { int processIndex = queue.poll(); if (remainingTime[processIndex] <= quantum) { time += remainingTime[processIndex]; remainingTime[processIndex] = 0; } else { time += quantum; remainingTime[processIndex] -= quantum; } while (processIndex < n && arrivalTime[processIndex] <= time) { queue.add(processIndex++); } if (remainingTime[processIndex] > 0) { queue.add(processIndex); } waitingTime[processIndex] = time - burstTime[processIndex] - arrivalTime[processIndex]; turnaroundTime[processIndex] = time - arrivalTime[processIndex]; } for (int i = 0; i < n; i++) { totalWaitingTime += waitingTime[i]; totalTurnaroundTime += turnaroundTime[i]; } System.out.println("Process\tArrival Time\tBurst Time\tWaiting Time\tTurnaround Time"); for (int i = 0; i < n; i++) { System.out.println(process[i] + "\t\t" + arrivalTime[i] + "\t\t" + burstTime[i] + "\t\t" + waitingTime[i] + "\t\t" + turnaroundTime[i]); } System.out.println("Average Waiting Time: " + (float) totalWaitingTime / n); System.out.println("Average Turnaround Time: " + (float) totalTurnaroundTime / n); } } ``` 上述代码中,我们使用了一个队列来存储进程,每次从队列中取出一个进程,并根据时间片的大小来执行进程。如果进程的剩余时间小于等于时间片,则执行完该进程;否则,将该进程重新加入队列中,等待下一次执行。同时,我们还计算了每个进程的等待时间和周转时间,并输出了平均等待时间和平均周转时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值