处理机调度算法

本文介绍了Java程序中进程类JCB的设计,包括到达时间、服务时间和周转时间等属性,并详细讲解了先来先服务(FCFS)、短作业优先(SJF)和最高响应比优先(HRRN)调度算法的实现。通过实例展示了如何在时间轮转调度算法中计算进程的真实服务时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import java.util.*;

class JCB {
    String name;// 进程名
    int arriveTime;// 到达时间
    int serveTime;// 服务时间
    int beginTime;// 开始时间
    int finishTime;// 结束时间
    int roundTime;// 周转时间
    double aveRoundTime;// 带权周转时间
    double clock = 0;// 在时间轮转调度算法中,记录该进程真实服务时间已经用时的时长
    int waitTime;// 记录每个进程到达后的等待时间,只用于最高响应比优先调度算法中
    boolean firstTimeTag = false;// 在RR算法中标识开始时间是否第一次计算


    public JCB(String name, int arriveTime, int serveTime, double waitTime) {

        this.name = name;
        this.arriveTime = arriveTime;
        this.serveTime = serveTime;
        this.waitTime = 0;
    }

    public String toString() {
        String info = new String("进程名:P" + this.name);
        return info;
    }

}

class processMenu {

    ArrayList<JCB> jcb;// 存放所有进程
    LinkedList<JCB> link;// 存放已经进入队列的进程
    ArrayList<JCB> new_jcb;// 存放按指定调度算法排序后的进程
    JCB nowProess;// 当前应执行进程

    public void init() {// 初始化
        jcb = new ArrayList<JCB>();
        link = new LinkedList<JCB>();
        new_jcb = new ArrayList<JCB>();
        JCB p1 = new JCB("1", 0, 4, 3);
        JCB p2 = new JCB("2", 1, 3, 2);
        JCB p3 = new JCB("3", 2, 5, 3);
        JCB p4 = new JCB("4", 3, 2, 1);
        JCB p5 = new JCB("5", 4, 4, 5);
        jcb.add(p1);
        jcb.add(p2);
        jcb.add(p3);
        jcb.add(p4);
        jcb.add(p5);
        // 先将jcb排序,便于下面的算法实现,就不需要再定义一个标识进程是否已到达的boolean,即无需每次都从头开始扫描jcb容器,
        // 而是用一个K记录下当前已经扫描到的位置,一次遍历即可,提高了算法效率。
        Collections.sort(jcb, new compareAt_St());
    }

    public void FCFS() {// 先来先服务算法
        ProcessQueue pq = new ProcessQueue();// 调用内部类
        pq.EnqueueLast();// 让最先到达的进程先入队
        System.out.println("*****************************************************");
        while (!link.isEmpty()) {// while(new_jcb.size()!=jcb.size())
            pq.DisplayQueue();// 打印当前队列中的进程
            pq.Dequeue();// 出队,一次一个
            pq.EnqueueLast();// 已到达的进程入队
        }
    }

    public void SJF() {// 短作业优先算法
        ProcessQueue pq = new ProcessQueue();
        pq.EnqueueLast();
        System.out.println("*****************************************************");
        while (!link.isEmpty()) {
            pq.DisplayQueue();// 打印当前队列中的进程
            pq.Dequeue();// 出队,一次一个
            pq.EnqueueLast();// 已到达的进程入队
            Collections.sort(link, new compareSt());// 队列中的进程还需按服务时间长度进行排序
        }
    }

    public void HRRN() {// 最高响应比优先调度算法
        ProcessQueue pq = new ProcessQueue();
        pq.EnqueueLast();
        System.out.println("*****************************************************");
        while (!link.isEmpty()) {
            pq.DisplayQueue();// 打印当前队列中的进程
            pq.Dequeue();// 出队,一次一个
            pq.EnqueueLast();// 已到达的进程入队
            Collections.sort(link, new comparePriority());// 队列中的进程还需按响应比进行排序
        }
    }

    class ProcessQueue {
        int k = 0;// jcb中的进程遍历时的下标
        int nowTime = 0;// 当前时间
        double sliceTime;// 轮转调度时间片
        int i = 0;// 记录当前出入队列的次数

        public void EnqueueLast() {// 进程首次入队,可一次进多个,从队尾进入
            while (k < jcb.size()) {// 当遍历完jcb中的所有进程时结束
                if (jcb.get(k).arriveTime <= nowTime) {// 已经到达的进程按到达时间先后进入队列
                    link.addLast(jcb.get(k));
                    k++;
                } else {
                    break;// 如果该进程还未入队,即先结束遍历,保留当前下标k值,注意:此处不要k--;
                }
            }
        }

        public void EnqueueFirst() {// 进程首次入队,可一次进多个,从队首进入
            while (k < jcb.size()) {// 当遍历完jcb中的所有进程时结束
                if (jcb.get(k).arriveTime <= nowTime) {// 已经到达的进程按到达时间先后进入队列
                    link.addFirst(jcb.get(k));
                    k++;
                } else {
                    break;// 如果该进程还未入队,即先结束遍历,保留当前下标k值,注意:此处不要k--;
                }
            }
        }

        public void Dequeue() {// 进程出队,一次只出一个
            nowProess = link.removeFirst();// 移除队列的队首元素并且返回该对象元素
            nowProess.beginTime = nowTime;// 计算开始时间,即为上一个进程的结束时间
            nowProess.finishTime = nowProess.beginTime + nowProess.serveTime;// 计算结束时间,该进程开始时间+服务时间
            nowProess.roundTime = nowProess.finishTime - nowProess.arriveTime;// 计算周转时间
            nowProess.aveRoundTime = (double) nowProess.roundTime / nowProess.serveTime;// 计算平均周转时间
            nowTime = nowProess.finishTime;// 获得结束时间,即当前时间,方便判断剩下的进程是否已到达
            new_jcb.add(nowProess);// 经处理过数据后加入new_jcb容器
            for (int i = 0; i < link.size(); ++i) {
                link.get(i).waitTime++;// 所有进入等待队列的进程等待时间+1,此处只为最高响应比算法所用
            }
        }

        public void Dequeue(double sliceTime) {// 重载Dequeue方法,实现轮转调度算法的出队
            nowProess = link.removeFirst();// 移除队列的队首元素并且返回该对象元素
            if (nowProess.firstTimeTag == false) {
                /*
                 * 轮转调度进程可能会多次反复进出队列,不像FCFS和SJF的进程只会进出一次,所以计算开始时间可以设个标志位,让每个进程在
                 * 第一次执行时记录一遍即可
                 */
                nowProess.beginTime = nowTime;// 进程开始执行的时间
                nowProess.firstTimeTag = true;// 计算第一次即可,下次无需更新计算
            }
            nowTime += sliceTime;// 每次出队,用时一个时间片,更新当前时间
            nowProess.clock += sliceTime;// 更新当前出队列的进程已服务时间
            if (nowProess.clock >= nowProess.serveTime) {
                nowProess.finishTime = nowTime;// 计算该进程完成时间
                nowProess.roundTime = nowProess.finishTime - nowProess.arriveTime;// 计算周转时间
                nowProess.aveRoundTime = (double) nowProess.roundTime / nowProess.serveTime;// 计算平均周转时间
                new_jcb.add(nowProess);// 经处理过数据后加入new_jcb容器
                EnqueueFirst();// 已到达的进程先入队
            } else {
                EnqueueFirst();// 已到达的进程先入队
                link.addLast(nowProess);// 上一轮出的再紧接着进入队尾
            }
        }

        public void DisplayQueue() {// 队列中等候的进程
            i++;
            System.out.println("第" + i + "次队列中排队的进程:" + link);
        }
    }

    public void printProcess() {
        System.out.println("进程名 到达时间  服务时间   开始时间  完成时间  周转时间  带权周转时间");
        for (int i = 0; i < new_jcb.size(); ++i) {
            System.out.println("P" + new_jcb.get(i).name + "   " + new_jcb.get(i).arriveTime + "      " +
                    new_jcb.get(i).serveTime + "     " + new_jcb.get(i).beginTime + "     " + new_jcb.get(i).finishTime +
                    "     " + new_jcb.get(i).roundTime + "    " + new_jcb.get(i).aveRoundTime);
        }
        new_jcb.clear();// 清空new_jcb容器内的内容,方便存储各种算法的结果并展示
    }
}

class compareSt implements Comparator<JCB> {// 按服务时间升序
    public int compare(JCB arg0, JCB arg1) {
        return arg0.serveTime - arg1.serveTime;
    }
}

class compareAt_St implements Comparator<JCB> {// 按到达时间升序,若到达时间相同,按服务时间升序
    public int compare(JCB o1, JCB o2) {
        int a = o1.arriveTime - o2.arriveTime;
        if (a > 0)
            return 1;
        else if (a == 0) {
            return o1.serveTime > o2.serveTime ? 1 : -1;
        } else
            return -1;
    }
}

class comparePriority implements Comparator<JCB> {// 按响应比升序排序

    public int compare(JCB o1, JCB o2) {
        double r1 = (double) o1.waitTime / o1.serveTime;
        double r2 = (double) o2.waitTime / o2.serveTime;
        return r1 > r2 ? 1 : -1;
    }

}

public class TestProcess {
    public static void main(String[] args) {
        processMenu pm = new processMenu();
        pm.init();// 初始化容器
        System.out.println("请输入您想看到的进程调度结果序号即可:\n" +
                "输入1:先来先服务调度算法\n" +
                "输入2:短作业优先调度算法\n" +
                "输入3:最高响应比调度算法\n" +
                "输入0:结束进程");
        Scanner in=new Scanner(System.in);
        int data=in.nextInt();

    switch (data) {
        case 1:
            pm.FCFS();
            pm.printProcess();
            break;
        case 2:
            pm.SJF();
            pm.printProcess();
            break;
        case 3:
            pm.HRRN();
            pm.printProcess();
            break;

        case 0:
            System.exit(0);
            break;
    }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超翔之逸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值