操作系统--响应比最高者优先算法(只需80行Python代码)

响应比最高者优先算法

简介

响应比最高者优先算法(Highest Respone Patio First,HRRF)是介于这两种算法(FCFS和SJF)之间的一种折中的策略,既考虑了作业等待时间,又考虑了作业的运行时间,这样既照顾了短作业又不使长作业的等待时间过长,改进了调度性能。缺点是每次计算各道作业响应比会有一定的时间开销,需要估计期待的服务时间,性能要比SJF略差。

原理

采用HRRF算法进行调度时,必须对输入井中的所有作业计算出各自的响应比,从资源能得到满足的作业中选择响应比最高的作业优先转入主存运行。
响应比的定义为:
响应比 = (作业等待时间 + 作业运行时间)/ 作业运行时间 ==> 响应比 = 作业响应时间 / 作业运行时间
作业从进入输入井到执行完成就是该作业的响应过程,因此该作业的响应时间就是作业的等待时间与运行时间之和。从响应比公式可以看出:

  1. 若作业的等待时间相同,则运行时间越短的作业,其响应比越高,因而该算法有利于短作业;
  2. 若作业的运行时间相同,则作业的等待时间越长,其响应比越高,因而该算法实现的时“先来先服务”;
  3. 对于长作业,作业的响应比随等待时间的增加而提高,当其等待时间足够长时,其响应比便可提升到很高,不至于发生饥饿现象。

Python代码

(1) 原始数据

作业名进入时间运行时间/min
JOB25050
JOB36010
JOB10120
JOB411020

(2) 代码实现

1.创建进程
def Creat():
    dic = {}
    i = 0
    while True:
        name = input("请输入进程名(输入Z结束):")
        if name == 'Z':
            return dic
        enter_time = eval(input("请输入进入时间:"))
        run_time = eval(input("请输入运行时间:"))
        values = {i:{'作业名': name,
                     '进入时间': enter_time,
                     '运行时间': run_time,
                     '开始时间': enter_time,
                     '完成时间': enter_time+run_time,
                     '周转时间': run_time,
                     '带权周转时间': 1}}
        dic.update(values)
        i += 1
        

创建一个大字典,大字典的键为数字,作为最后的输出顺序。而键所对应的值是字典类型的。用于储存作业的各个数据。
首先数据的初始化都默认是第一个作业被执行所生成的数据(方便找到第一个作业后可以直接跳过修改阶段)。
当作业名为Z时,作业的创建结束。

2.第一次排序
def first_sort(data):
    for i in range(len(data)):
        Min = data[i]
        cnt = i
        for j in range(i, len(data)):
            if Min['进入时间'] > data[j]['进入时间']:
                Min = data[j]
                cnt = j
        temp = data[i]
        data[i] = Min
        data[cnt] = temp

这一步比较有趣,我是以进入时间为对象,使用冒泡排序对作业进行排序。索引越小对应的键里的进入时间越早,即作业被创建的越早,索引值越小。

第一次排序后的结果

作业名进入时间运行时间/min
JOB10120
JOB25050
JOB36010
JOB411020
3. 找出在作业结束前被创建的作业
def Select_enter_time(data,finish,i):
    dic = {}
    for j in range(i, len(data)):
        if finish >= data[j]['进入时间']:
            ans = {j: data[j]}
            dic.update(ans)
    return dic

这一步可能会有些迷,但是又是必不可少的一步,少了这步就可能出现BUG(即还没创建就开始执行)。所以这一步就是在进行筛选,找出符合条件的作业。

4.找出响应比最大的作业相对应的索引(大字典的键)
def Response(Filter,finish,i):
    MAX = (finish-Filter[i]['进入时间']+Filter[i]['运行时间'])/Filter[i]['运行时间']
    MAX_cnt = i
    for j in range(i, len(Filter)):
        wait = finish-Filter[j]['进入时间']
        res_time = (wait+Filter[j]['运行时间'])/Filter[j]['运行时间']
        if MAX < res_time:
            MAX = res_time
            MAX_cnt = j
    return MAX_cnt

在符合条件的作业下,找出响应比最大的作业的索引,因为在主函数中需要进行小字典(即作业)的交换。

5.修改数据
def Write(data,finish,i):
    data[i]['开始时间'] = finish
    data[i]['完成时间'] = finish + data[i]['运行时间']
    data[i]['周转时间'] = data[i]['完成时间'] - data[i]['进入时间']
    data[i]['带权周转时间'] = data[i]['周转时间'] / data[i]['运行时间']

修改开始时间、完成时间、周转时间、带权周转时间。

6.打印输出
def PPrint(data):
    SZ,SD = 0, 0
    for i in range(len(data)):
        print(data[i])
        SZ+=data[i]['周转时间']
        SD+=data[i]['带权周转时间']
    print("平均周转时间{0:.2f},平均带权周转时间{1:.2f}".format(SZ/len(data),SD/len(data)))

打印输出数据

7.主函数
def main():
    data = Creat()
    first_sort(data)
    finish = data[0]['完成时间']
    for i in range(1, len(data)):
        Filter = Select_enter_time(data, finish, i)
        if Filter == {}:
            break
        Index = Response(Filter, finish, i)
        temp = data[i]
        data[i] = Filter[Index]
        data[Index] = temp
        Write(data,finish,i)
        finish = data[i]['完成时间']
    PPrint(data)

if __name__ == '__main__':
    main()

将Create()创建的作业赋值给data,然后对作业进行第一次排序first_sort(data),将第一个被执行作业的结束时间赋值给finish。进入for循环,每进行一次for循环,大字典{1:{作业},2:{作业},…,i:{作业}}已经排好执行顺序,这个for 循环相当于一个变形的顺序排序。

8.完整代码
def Creat():
    dic = {}
    i = 0
    while True:
        name = input("请输入进程名(输入Z结束):")
        if name == 'Z':
            return dic
        enter_time = eval(input("请输入进入时间:"))
        run_time = eval(input("请输入运行时间:"))
        values = {i:{'作业名': name,
                     '进入时间': enter_time,
                     '运行时间': run_time,
                     '开始时间': enter_time,
                     '完成时间': enter_time+run_time,
                     '周转时间': run_time,
                     '带权周转时间': 1}}
        dic.update(values)
        i += 1

def first_sort(data):
    for i in range(len(data)):
        Min = data[i]
        cnt = i
        for j in range(i, len(data)):
            if Min['进入时间'] > data[j]['进入时间']:
                Min = data[j]
                cnt = j
        temp = data[i]
        data[i] = Min
        data[cnt] = temp

def Select_enter_time(data,finish,i):
    dic = {}
    for j in range(i, len(data)):
        if finish >= data[j]['进入时间']:
            ans = {j: data[j]}
            dic.update(ans)
    return dic

def Response(Filter,finish,i):
    MAX = (finish-Filter[i]['进入时间']+Filter[i]['运行时间'])/Filter[i]['运行时间']
    MAX_cnt = i
    for j in range(i, len(Filter)):
        wait = finish-Filter[j]['进入时间']
        res_time = (wait+Filter[j]['运行时间'])/Filter[j]['运行时间']
        if MAX < res_time:
            MAX = res_time
            MAX_cnt = j
    return MAX_cnt

def Write(data,finish,i):
    data[i]['开始时间'] = finish
    data[i]['完成时间'] = finish + data[i]['运行时间']
    data[i]['周转时间'] = data[i]['完成时间'] - data[i]['进入时间']
    data[i]['带权周转时间'] = data[i]['周转时间'] / data[i]['运行时间']

def PPrint(data):
    SZ,SD = 0, 0
    for i in range(len(data)):
        print(data[i])
        SZ+=data[i]['周转时间']
        SD+=data[i]['带权周转时间']
    print("平均周转时间{0:.2f},平均带权周转时间{1:.2f}".format(SZ/len(data),SD/len(data)))

def main():
    data = Creat()
    first_sort(data)
    finish = data[0]['完成时间']
    for i in range(1, len(data)):
        Filter = Select_enter_time(data, finish, i)
        if Filter == {}:
            break
        Index = Response(Filter, finish, i)
        temp = data[i]
        data[i] = Filter[Index]
        data[Index] = temp
        Write(data,finish,i)
        finish = data[i]['完成时间']
    PPrint(data)

if __name__ == '__main__':
    main()

9.输出
请输入进程名(输入Z结束):JOB1
请输入进入时间:0
请输入运行时间:120
请输入进程名(输入Z结束):JOB2
请输入进入时间:50
请输入运行时间:50
请输入进程名(输入Z结束):JOB3
请输入进入时间:60
请输入运行时间:10
请输入进程名(输入Z结束):JOB4
请输入进入时间:110
请输入运行时间:20
请输入进程名(输入Z结束):Z
{'作业名': 'JOB1', '进入时间': 0, '运行时间': 120, '开始时间': 0, '完成时间': 120, '周转时间': 120, '带权周转时间': 1}
{'作业名': 'JOB3', '进入时间': 60, '运行时间': 10, '开始时间': 120, '完成时间': 130, '周转时间': 70, '带权周转时间': 7.0}
{'作业名': 'JOB2', '进入时间': 50, '运行时间': 50, '开始时间': 130, '完成时间': 180, '周转时间': 130, '带权周转时间': 2.6}
{'作业名': 'JOB4', '进入时间': 110, '运行时间': 20, '开始时间': 180, '完成时间': 200, '周转时间': 90, '带权周转时间': 4.5}
平均周转时间102.50,平均带权周转时间3.77
相关推荐
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页