【Python】(六)用队列实现对打印机使用情况的模拟

python实现队列的代码回顾

class Queue():
    # Queue() 创建一个空的新队列。 它不需要参数,并返回一个空队列。
    def __init__(self):
        self.items = []
    
    # enqueue(item) 将新项添加到队尾。 它需要 item 作为参数,并不返回任何内容。
    def enqueue(self, item):
        self.items.insert(0, item)
    
    # dequeue() 从队首移除项。它不需要参数并返回 item。 队列被修改。
    def dequeue(self):
        item = self.items.pop()
        return item
    
    # isEmpty() 查看队列是否为空。它不需要参数,并返回布尔值。
    def isEmpty(self):
        return 0 == len(self.items)
        
    # size() 返回队列中的项数。它不需要参数,并返回一个整数。
    def size(self):
        length = len(self.items)
        return length

问题描述

假设实验室里有一台打印机供学生共性。当学生向共享打印机发送打印任务时,任务被放置在队列中以便以先来先服务的方式被处理。如何才能通过python程序模拟的方式得到每次提交任务的平均等待时间呢?(平均等待时间不包括打印本身的时间,仅指在队列中排队的时间。)
我们假定:

  1. 学生们每次打印的页数在1到20页之间。
  2. 打印机平均每小时会收到20个打印请求,即平均每180秒1个请求。
  3. 每秒新增任务的可能性相等,即任务的产生为独立同分布
  4. 打印机的打印速度恒定。

总体模拟思路

当学生提交打印任务时,我们将把他们添加到打印任务的等待队列。当打印机完成任务时,它将检查队列,将剩余的任务中队首的那一个弹出并处理。学生等待他们的任务打印的平均时间也等于任务在队列中等待的平均时间。
我们将对每个任务入队和出队的时间戳进行记录,由此得到该任务在队列中的等待时间。

对任务的模拟

任务类应包括以下几个功能:随机生成页数、记录入队时间戳、返回需要打印的页数、根据当前时间戳返回等待的时间。

class Task:
    #任务初始化
    def __init__(self, time):
        # time 为传入的任务创建时间,也就是入队时间
        self.in_time = time
        self.pages = random.randrange(1,21) # 随机生成1到20页之间的页数
    
    #返回任务需要打印的页数
    def getPage(self):
        return self.pages
    
    def waitTime(self, out_time):
        # out_time为当前时间戳
        return out_time - self.in_time

对打印机的模拟

打印机类应包括以下几个功能:设定打印速度(多少秒每页)、载入新任务并计算新任务剩余打印时间、记录当前任务的剩余打印时间、打印(即减少已载入任务的剩余打印时间)。

class Printer:
    #打印机初始化
    def __init__(self, timeperpage):
        #timeperpage 为每页打印所需要的时间,设定好后便是恒定的值
        self.timeperpage = timeperpage
        self.current_task = None #记录当前正在处理的任务
        self.remaining_time = 0 #记录当前任务的剩余处理时间
    
    #返回打印机中是否有任务
    def isBusy(self):
        return self.current_task != None
    
    #载入新的任务
    def loadTask(self, next_task):
        # next_task 为新的任务
        self.current_task = next_task
        self.remaining_time = next_task.getPage()*self.timeperpage #计算新的剩余打印时间
    
    #打印
    def printTask(self):
        if self.isBusy(): #有任务需要处理
            self.remaining_time -= 1 # 打印,也就是将剩余打印时间减一
            if self.remaining_time <= 0: # 当前任务打印结束
                self.current_task = None
        else: #空闲中
            pass

借助队列模拟打印情况,并计算平均等待时间

由于任务的产生为独立同分布,我们可以在每一秒上运行1到180间随机数生成,当值为1时产生新任务请求,以模拟每180秒一个新任务的任务产生速度。

def simulation(total_time, timeperpage):
    # total_time为总的实验时间,timeperpage为每页打印所需要的时间
    waiting_time = [] #记录每个任务的等待时间
    
    printer = Printer(timeperpage) #初始化打印机
    waitQueue = Queue() #初始化任务等待队列
    
    for second in range(total_time):
        
        rand_num = random.randrange(1,181) #产生1到180之间的随机数
        if rand_num == 1:
            new_task = Task(second) #产生新任务
            waitQueue.enqueue(new_task) #新任务进入等待队列
            
        if (not printer.isBusy()) and (not waitQueue.isEmpty()): #打印机空闲并且有任务在等待
            next_task = waitQueue.dequeue() # 弹出下一个任务
            waiting_time.append(new_task.waitTime(second)) # 计算并记录等待时间
            printer.loadTask(next_task) #载入新的任务
        
        printer.printTask() #打印
    
    average_time = sum(waiting_time)/len(waiting_time)
    return average_time

完整实验代码如下:

import random

class Queue():
    # Queue() 创建一个空的新队列。 它不需要参数,并返回一个空队列。
    def __init__(self):
        self.items = []
    
    # enqueue(item) 将新项添加到队尾。 它需要 item 作为参数,并不返回任何内容。
    def enqueue(self, item):
        self.items.insert(0, item)
    
    # dequeue() 从队首移除项。它不需要参数并返回 item。 队列被修改。
    def dequeue(self):
        item = self.items.pop()
        return item
    
    # isEmpty() 查看队列是否为空。它不需要参数,并返回布尔值。
    def isEmpty(self):
        return 0 == len(self.items)
        
    # size() 返回队列中的项数。它不需要参数,并返回一个整数。
    def size(self):
        length = len(self.items)
        return length

class Task:
    #任务初始化
    def __init__(self, time):
        # time 为传入的任务创建时间,也就是入队时间
        self.in_time = time
        self.pages = random.randrange(1,21) # 随机生成1到20页之间的页数
    
    #返回任务需要打印的页数
    def getPage(self):
        return self.pages
    
    def waitTime(self, out_time):
        # out_time为当前时间戳
        return out_time - self.in_time
        
class Printer:
    #打印机初始化
    def __init__(self, timeperpage):
        #timeperpage 为每页打印所需要的时间,设定好后便是恒定的值
        self.timeperpage = timeperpage
        self.current_task = None #记录当前正在处理的任务
        self.remaining_time = 0 #记录当前任务的剩余处理时间
    
    #返回打印机中是否有任务
    def isBusy(self):
        return self.current_task != None
    
    #载入新的任务
    def loadTask(self, next_task):
        # next_task 为新的任务
        self.current_task = next_task
        self.remaining_time = next_task.getPage()*self.timeperpage #计算新的剩余打印时间
    
    #打印
    def printTask(self):
        if self.isBusy(): #有任务需要处理
            self.remaining_time -= 1 # 打印,也就是将剩余打印时间减一
            if self.remaining_time <= 0: # 当前任务打印结束
                self.current_task = None
        else: #空闲中
            pass

def simulation(total_time, timeperpage):
    # total_time为总的实验时间,timeperpage为每页打印所需要的时间
    waiting_time = [] #记录每个任务的等待时间
    
    printer = Printer(timeperpage) #初始化打印机
    waitQueue = Queue() #初始化任务等待队列
    
    for second in range(total_time):
        
        rand_num = random.randrange(1,181) #产生1到180之间的随机数
        if rand_num == 1:
            new_task = Task(second) #产生新任务
            waitQueue.enqueue(new_task) #新任务进入等待队列
            
        if (not printer.isBusy()) and (not waitQueue.isEmpty()): #打印机空闲并且有任务在等待
            next_task = waitQueue.dequeue() # 弹出下一个任务
            waiting_time.append(new_task.waitTime(second)) # 计算并记录等待时间
            printer.loadTask(next_task) #载入新的任务
        
        printer.printTask() #打印
    
    average_time = sum(waiting_time)/len(waiting_time)
    return average_time
    
def main():
    timeperpage = 5
    total_time = 36000 #10小时
    print("-----------------")
    for i in range(10):
        average_time = simulation(total_time,timeperpage)
        print("平均等待打印时间为:%.5f 秒"%average_time)
        print("-----------------")

if __name__ == "__main__":
    main()

我们选定10小时为模拟时间,当 timeperpage 为 1 时,运行结果:

-----------------
平均等待打印时间为:0.11966 秒
-----------------
平均等待打印时间为:0.46847 秒
-----------------
平均等待打印时间为:0.31754 秒
-----------------
平均等待打印时间为:0.38251 秒
-----------------
平均等待打印时间为:0.46087 秒
-----------------
平均等待打印时间为:0.30808 秒
-----------------
平均等待打印时间为:0.24670 秒
-----------------
平均等待打印时间为:0.40659 秒
-----------------
平均等待打印时间为:0.27869 秒
-----------------
平均等待打印时间为:0.30055 秒
-----------------

当 timeperpage 为 5 时,运行结果:

-----------------
平均等待打印时间为:11.33854 秒
-----------------
平均等待打印时间为:8.60104 秒
-----------------
平均等待打印时间为:13.73057 秒
-----------------
平均等待打印时间为:9.30270 秒
-----------------
平均等待打印时间为:9.01156 秒
-----------------
平均等待打印时间为:12.09268 秒
-----------------
平均等待打印时间为:13.05405 秒
-----------------
平均等待打印时间为:8.96023 秒
-----------------
平均等待打印时间为:13.79907 秒
-----------------
平均等待打印时间为:9.56500 秒
-----------------

当 timeperpage 为 10 时,运行结果:

-----------------
平均等待打印时间为:44.32461 秒
-----------------
平均等待打印时间为:58.77295 秒
-----------------
平均等待打印时间为:44.65238 秒
-----------------
平均等待打印时间为:49.37629 秒
-----------------
平均等待打印时间为:54.00000 秒
-----------------
平均等待打印时间为:47.69378 秒
-----------------
平均等待打印时间为:49.18557 秒
-----------------
平均等待打印时间为:54.68367 秒
-----------------
平均等待打印时间为:58.63158 秒
-----------------
平均等待打印时间为:56.18391 秒
-----------------

每页所需时间越短,说明打印机速度越快,因而平均等待时间越短。这与实验数据是相符的。

    原文作者:hitsunbo
    原文地址: https://www.jianshu.com/p/df116d5d103c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞