操作系统~按优先数调度算法实现处理器调度(Java)

目录

一、实验目的

二、实验原理

三、算法流程图及关键算法解析

1.算法流程图

2.关键算法解析

四、源代码及注释

五、测试用例及测试代码 


一、实验目的

在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。当就绪进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。本实验模拟在单处理器情况下的处理器调度,帮助学生加深了解处理器调度的工作。

二、实验原理

设计一个按优先数调度算法实现处理器调度的程序。

 (1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:

其中,进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。

指针——按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。

要求运行时间——假设进程需要运行的单位时间数。

优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。

状态——可假设有两种状态,“就绪”状态和“结束”状态。五个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。

(2) 在每次运行你所设计的处理器调度程序之前,为每个进程任意确定它的“优先数”和“要求运行时间”。

(3) 为了调度方便,把五个进程按给定的优先数从大到小连成队列。用一单元指出队首进程,用指针指出队列的连接情况。例:

(4) 处理器调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行一次优先数就减“1”。由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:

优先数-1,运行时间-1

来模拟进程的一次运行。

提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。

(5) 进程运行一次后,若要求运行时间¹0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它的状态修改成“结束”(E),且退出队列。

(6) 若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。

(7) 在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。

(8) 为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。

三、算法流程图及关键算法解析

1.算法流程图

2.关键算法解析

        以链表的数据存储方式来实现了处理器调度,其关键算法在于入队操作,出队操作较为简单,每次取出队首元素(即链表的头结点)即可.

(1)首先将所有进程按照其优先级数大小加入队列,从链表头结点到尾结点按从大到小的顺序.

(2)每次运行优先级数最高的一个进程,运行结束后,优先级数-1,要求运行时间-1,并将其重新按照优先级数的大小重新插入链表中.

(3)在将进程入队时,进行如下几个判断:

①如果此时进程的要求运行时间为0,则将其状态修改为“E”,并退出该进程

        if(node.time == 0) {
            node.statue = 'E';
            System.out.println(node.pcbName + "退出进程队列");
            System.out.println(node + "\n");
            return;
        }

②如果入队进程的优先级数比头结点大,则将其以头插法插入 

        //如果node的优先级比头结点大
        if(node.priority > this.head.priority) {
            node.next = this.head;
            this.head = node;
            return;
        }

③如果入队进程的优先级数不比头结点大,则寻找到指定位置将其插入

        //如果node的优先级不比头结点大,也不与头结点相等
        PCB cur = this.head;
        while(cur.next != null) {
            if(cur.next.priority < node.priority) {
                PCB curNext = cur.next;
                node.next = curNext;
                cur.next = node;
                return;
            }
            //如果node的优先级与头结点相等,按先来先服务原则
            if(cur.next.priority == node.priority) {
                PCB curNext = cur.next;
                node.next = curNext.next;
                curNext.next = node;
                return;
            }
            cur = cur.next;
        }
        //此时如果还未结束,则node应该直接插入到队尾
        cur.next = node;
        node.next = null;
    }

 

四、源代码及注释

/**
 * 定义进程控制块PCB
 */
public class PCB {
    public String pcbName;//进程名
    public PCB next;//指针
    public int time;//运行时间
    public int priority;//优先数
    public char statue = 'R';//进程的状态,初始化为就绪态

    //构造方法
    public PCB(String pcbName, int time, int priority) {
        this.pcbName = pcbName;
        this.time = time;
        this.priority = priority;
    }

    //重写toString方法
    @Override
    public String toString() {
        return "进程名='" + pcbName + '\'' +
                ", 要求运行时间=" + time +
                ", 优先级数=" + priority +
                ", 状态=" + statue;
    }
}

/**
 * 按优先数调度算法模拟实现处理器调度
 */
class ProcessScheduling {
    private PCB head;

    /**
     * PCB对象插入操作,根据每一个进程的优先级数进行插入
     * 如果优先级数相等,则按先来先服务原则进行插入
     * @param node
     */
    public void addPCB(PCB node) {
        //若要求运行时间=0,则把它的状态修改成“结束”(E),且退出队列
        if(node.time == 0) {
            node.statue = 'E';
            System.out.println(node.pcbName + "退出进程队列");
            System.out.println(node + "\n");
            return;
        }
        //若头结点为空
        if(this.head == null) {
            this.head = node;
            return;
        }
        //边插入边按优先级进行排序

        //如果node的优先级比头结点大
        if(node.priority > this.head.priority) {
            node.next = this.head;
            this.head = node;
            return;
        }
        //如果node的优先级与头结点相等,按先来先服务原则
        if(node.priority == this.head.priority) {
            node.next = this.head.next;
            this.head.next = node;
            return;
        }
        //如果node的优先级不比头结点大,也不与头结点相等
        PCB cur = this.head;
        while(cur.next != null) {
            if(cur.next.priority < node.priority) {
                PCB curNext = cur.next;
                node.next = curNext;
                cur.next = node;
                return;
            }
            //如果node的优先级与头结点相等,按先来先服务原则
            if(cur.next.priority == node.priority) {
                PCB curNext = cur.next;
                node.next = curNext.next;
                curNext.next = node;
                return;
            }
            cur = cur.next;
        }
        //此时如果还未结束,则node应该直接插入到队尾
        cur.next = node;
        node.next = null;
    }

    /**
     * 优先数调度算法模拟实现处理器调度的运行
     * 每一次运行优先级数最高的一个进程,运行结束后再将其插入到队列中
     */
    public void runPCB() {
        while(this.head != null) {
            //运行优先级最高的第一个进程
            PCB cur = this.head;
            this.head = this.head.next;
            System.out.println();
            System.out.println("开始执行" + cur.pcbName + "进程");
            System.out.println(cur);
            //cur的运行优先级数-1
            cur.priority -= 1;
            //cur的运行时间-1
            cur.time -= 1;
            System.out.println(cur.pcbName + "进程执行完毕");
            System.out.println();
            //再将cur插入进程队列
            addPCB(cur);
            //打印每次被选中进程的进程运行一次后进程队列的变化。
            if(this.head == null) {
                System.out.println("所有的线程执行完毕");
                return;
            }
            System.out.println("=====================");
            System.out.println("此时进程队列的所有进程信息");
            display();
            System.out.println("=====================");
        }
    }

    //打印进程队列
    public void display() {
        for(PCB pcb = this.head; pcb != null; pcb = pcb.next) {
            System.out.println(pcb);
        }
    }
}

五、测试用例及测试代码 

测试用例有五个进程,分别为:

public class TestPCB {
    public static void main(String[] args) {
        PCB[] pcbs = new PCB[5];
        pcbs[0] = new PCB("P1",2,1);
        pcbs[1] = new PCB("P2",3,5);
        pcbs[2] = new PCB("P3",1,3);
        pcbs[3] = new PCB("P4",2,4);
        pcbs[4] = new PCB("P5",4,2);
        ProcessScheduling p = new ProcessScheduling();
        for(PCB pcb : pcbs) {
            p.addPCB(pcb);
        }
        p.runPCB();
    }
}

运行结果 

开始执行P2进程
进程名='P2', 要求运行时间=3, 优先级数=5, 状态=R
P2进程执行完毕

=====================
此时进程队列的所有进程信息
进程名='P4', 要求运行时间=2, 优先级数=4, 状态=R
进程名='P2', 要求运行时间=2, 优先级数=4, 状态=R
进程名='P3', 要求运行时间=1, 优先级数=3, 状态=R
进程名='P5', 要求运行时间=4, 优先级数=2, 状态=R
进程名='P1', 要求运行时间=2, 优先级数=1, 状态=R
=====================

开始执行P4进程
进程名='P4', 要求运行时间=2, 优先级数=4, 状态=R
P4进程执行完毕

=====================
此时进程队列的所有进程信息
进程名='P2', 要求运行时间=2, 优先级数=4, 状态=R
进程名='P3', 要求运行时间=1, 优先级数=3, 状态=R
进程名='P4', 要求运行时间=1, 优先级数=3, 状态=R
进程名='P5', 要求运行时间=4, 优先级数=2, 状态=R
进程名='P1', 要求运行时间=2, 优先级数=1, 状态=R
=====================

开始执行P2进程
进程名='P2', 要求运行时间=2, 优先级数=4, 状态=R
P2进程执行完毕

=====================
此时进程队列的所有进程信息
进程名='P3', 要求运行时间=1, 优先级数=3, 状态=R
进程名='P2', 要求运行时间=1, 优先级数=3, 状态=R
进程名='P4', 要求运行时间=1, 优先级数=3, 状态=R
进程名='P5', 要求运行时间=4, 优先级数=2, 状态=R
进程名='P1', 要求运行时间=2, 优先级数=1, 状态=R
=====================

开始执行P3进程
进程名='P3', 要求运行时间=1, 优先级数=3, 状态=R
P3进程执行完毕

P3退出进程队列
进程名='P3', 要求运行时间=0, 优先级数=2, 状态=E

=====================
此时进程队列的所有进程信息
进程名='P2', 要求运行时间=1, 优先级数=3, 状态=R
进程名='P4', 要求运行时间=1, 优先级数=3, 状态=R
进程名='P5', 要求运行时间=4, 优先级数=2, 状态=R
进程名='P1', 要求运行时间=2, 优先级数=1, 状态=R
=====================

开始执行P2进程
进程名='P2', 要求运行时间=1, 优先级数=3, 状态=R
P2进程执行完毕

P2退出进程队列
进程名='P2', 要求运行时间=0, 优先级数=2, 状态=E

=====================
此时进程队列的所有进程信息
进程名='P4', 要求运行时间=1, 优先级数=3, 状态=R
进程名='P5', 要求运行时间=4, 优先级数=2, 状态=R
进程名='P1', 要求运行时间=2, 优先级数=1, 状态=R
=====================

开始执行P4进程
进程名='P4', 要求运行时间=1, 优先级数=3, 状态=R
P4进程执行完毕

P4退出进程队列
进程名='P4', 要求运行时间=0, 优先级数=2, 状态=E

=====================
此时进程队列的所有进程信息
进程名='P5', 要求运行时间=4, 优先级数=2, 状态=R
进程名='P1', 要求运行时间=2, 优先级数=1, 状态=R
=====================

开始执行P5进程
进程名='P5', 要求运行时间=4, 优先级数=2, 状态=R
P5进程执行完毕

=====================
此时进程队列的所有进程信息
进程名='P1', 要求运行时间=2, 优先级数=1, 状态=R
进程名='P5', 要求运行时间=3, 优先级数=1, 状态=R
=====================

开始执行P1进程
进程名='P1', 要求运行时间=2, 优先级数=1, 状态=R
P1进程执行完毕

=====================
此时进程队列的所有进程信息
进程名='P5', 要求运行时间=3, 优先级数=1, 状态=R
进程名='P1', 要求运行时间=1, 优先级数=0, 状态=R
=====================

开始执行P5进程
进程名='P5', 要求运行时间=3, 优先级数=1, 状态=R
P5进程执行完毕

=====================
此时进程队列的所有进程信息
进程名='P1', 要求运行时间=1, 优先级数=0, 状态=R
进程名='P5', 要求运行时间=2, 优先级数=0, 状态=R
=====================

开始执行P1进程
进程名='P1', 要求运行时间=1, 优先级数=0, 状态=R
P1进程执行完毕

P1退出进程队列
进程名='P1', 要求运行时间=0, 优先级数=-1, 状态=E

=====================
此时进程队列的所有进程信息
进程名='P5', 要求运行时间=2, 优先级数=0, 状态=R
=====================

开始执行P5进程
进程名='P5', 要求运行时间=2, 优先级数=0, 状态=R
P5进程执行完毕

=====================
此时进程队列的所有进程信息
进程名='P5', 要求运行时间=1, 优先级数=-1, 状态=R
=====================

开始执行P5进程
进程名='P5', 要求运行时间=1, 优先级数=-1, 状态=R
P5进程执行完毕

P5退出进程队列
进程名='P5', 要求运行时间=0, 优先级数=-2, 状态=E

所有的线程执行完毕

  • 10
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Li_yizYa

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

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

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

打赏作者

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

抵扣说明:

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

余额充值