Python的队列实例分析

Python的队列实例分析

这篇“Python的队列实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python的队列实例分析”文章吧。

    模拟打印机任务队列过程

    计算机科学中也有众多的队列例子。比如计算机实验室有10台计算机,它们都与同一台打印机相连。当学生需要打印的时候,他们的打印任务会进入一个队列。该队列中的第一个任务就是即将执行的打印任务。如果一个任务排在队列的最后面,那么它必须等到所有前面的任务都执行完毕后才能执行。

    学生向共享打印机发送打印请求,这些打印任务被存在一个队列中,并且按照先到先得的顺序执行。这样的设定可能导致很多问题。其中最重要的是,打印机能否处理一定量的工作。如果不能,学生可能会由于等待过长时间而错过要上的课。

    考虑计算机实验室里的这样一个场景:在任何给定的一小时内,实验室里都有10个学生。他们在这 一小时内最多打印2次,并且打印的页数从1到20页不等。实验室的打印机比较老旧,每分钟只能以低质量打印10页。也可以将打印质量调高,但是这样做会导致打印机每分钟只能打印5页。降低打印速度可能导致学生等待过长时间。那么,应该如何设置打印速度呢?

    可以通过构建一个模型来解决该问题。我们需要为学生打印任务打印机构建对象。当学生提交打印任务时,我们需要将它们加入打印机的任务队列中。当打印机执行完一个任务后,它会检查该队列,看看其中是否还有需要处理的任务。我们感兴趣的是学生平均需要等待多久才能拿到打印好的文章。这个时间等于打印任务在队列中的平均等待时间。

    在模拟时,需要应用一些概率学知识。举例来说,学生打印的文章可能有1~20页。如果各页数出现的概率相等,那么打印任务的实际时长可以通过模拟1~20的一个文章页数随机数来计算得出。

    如果实验室里有10个学生,并且在一小时内每个人都打印次,那么每小时平均就有20个打印任务。在任意一秒,创建一个打印请求的概率是多少?回答这个问题需要考虑任务与时间的比值。每小时20个任务相当于每180秒1个任务。

    可以通过1~180的一个随机数来模拟每秒内产生打印请求的概率(1/180的概率)。如果随机数正好是180,那么就认为有 一个打印请求被创建。注意,可能会出现多个请求接连被创建的情况,也可能很长一段时间内都没有请求。这就是模拟的本质。我们希望在常用参数已知的情况下尽可能准确地模拟。

    主要模拟步骤:

    1.创建一个打印任务队列。每一个任务到来时都会有一个时间戳。一开始,队列是空的。

    2.针对每一秒(currentSecond),执行以下操作。

    • 是否有新创建的打印任务?如果是,以currentSecond作为其时间戳并将该任务加入到队列中。

    • 如果打印机空闲,并且有正在等待执行的任务,执行以下操作:

      • 队列中取出第一个任务并提交给打印机;

      • currentSecond 减去该任务的时间戳,以此计算其等待时间

      • 将该任务的等待时间存入一个列表,用来作为计算平均等待时间的数据;

      • 根据该任务的页数,计算执行时间。

    • 打印机进行一秒的打印,同时从该任务的执行时间中减去一秒。

    • 如果打印任务执行完毕,即任务的执行时间减为0,则说明打印机回到空闲状态。

    3.当模拟完成之后,根据等待时间列表中的值计算平均等待时间。

    构建队列程序

    classQueue:def__init__(self):self.items=[]#构建空队列defisEmpty(self):returnself.items==[]#判断是否为空defenqueue(self,item):self.items.insert(0,item)#在队列尾部(列表左端)插入元素defdequeue(self):returnself.items.pop()#在队列头部(列表右端)移出元素defsize(self):returnlen(self.items)#队列(列表)长度

    模拟打印程序

    importrandom#模拟打印机classPrinter:#打印机初始化def__init__(self,ppm):self.pagerate=ppm#打印速度页/分钟self.currentTask=None#现有任务self.timeRemain=0#该任务所需时间#打印任务倒计时0代表打印完成deftick(self):#如果打印机正在执行任务ifself.currentTask!=None:#该任务执行时间=执行时间-1(执行时间倒计时)self.timeRemaining=self.timeRemaining-1ifself.timeRemaining<=0:#该任务执行时间<=0self.currentTask=None#该任务执行完毕#判断打印机是否空闲defbusy(self):ifself.currentTask!=None:returnTrueelse:returnFalse#打印机接受新任务defstartNext(self,newtask):self.currentTask=newtask#新打印任务需要时间=新任务页数*(60/每分钟打印多少页的速度)#(60/每分钟打印多少页的速度)=每打印一页所需要的秒数self.timeRemaining=newtask.getPages()*(60/self.pagerate)#模拟单个任务的属性classTask:#任务初始化def__init__(self,time):self.timestamp=time#创建任务的时间点self.pages=random.randrange(1,21)#任务页数在1~20间随机生成defgetStamp(self):returnself.timestamp#获取任务创建的时间点defgetPages(self):returnself.pages#获取任务的页数defwaitTime(self,currenttime):#任务的等待时间=当前时间-任务创建的时间点returncurrenttime-self.timestamp#模拟学生创建的新打印请求defnewPrintTask():#打印请求是一个随机事件#通过1~180之间的一个随机数来模拟每秒内产生打印请求的概率#如果随机数正好是180,那么就认为有一个打印请求被创建。num=random.randrange(1,181)ifnum==180:returnTrueelse:returnFalse#模拟打印过程defsimulation(numSeconds,pagesPerMinute):labprinter=Printer(pagesPerMinute)printQueue=Queue()waitingtimes=[]forcurrentSecondinrange(numSeconds):ifnewPrintTask():task=Task(currentSecond)printQueue.enqueue(task)if(notlabprinter.busy())and(notprintQueue.isEmpty()):nexttask=printQueue.dequeue()waitingtimes.append(nexttask.waitTime(currentSecond))labprinter.startNext(nexttask)labprinter.tick()averageWait=sum(waitingtimes)/len(waitingtimes)print("平均等待%6.2f秒,还有%3d个任务等待处理"%(averageWait,printQueue.size()))

    模拟打印过程(有注释)

    defsimulation(numSeconds,pagesPerMinute):#numSeconds-时间段#pagesPerMinute-打印速度,页/分钟labprinter=Printer(pagesPerMinute)#创建打印机printQueue=Queue()#创建打印机任务队列waitingtimes=[]#创建等待时间数据样本列表forcurrentSecondinrange(numSeconds):#一次循环代表一秒ifnewPrintTask():#如果有打印请求创建task=Task(currentSecond)#创建打印任务并记录当前时间点printQueue.enqueue(task)#打印任务进入打印机任务队列#如果打印机空闲并且打印机任务队列有任务if(notlabprinter.busy())and(notprintQueue.isEmpty()):nexttask=printQueue.dequeue()#从队列取出新任务#根据当前时间点计算新任务在任务队列里的等待时间并将等待时间记录进样本列表waitingtimes.append(nexttask.waitTime(currentSecond))labprinter.startNext(nexttask)#开始执行新任务打印机进入忙碌状态labprinter.tick()#每循环一次当前打印任务执行倒计时减少一秒averageWait=sum(waitingtimes)/len(waitingtimes)print("平均等待%6.2f秒,还有%3d个任务等待处理"%(averageWait,printQueue.size()))

    需要注意的是,时间戳是我们根据循环模拟出来的,我们给定了numSeconds 时间段后,每循环一次相当于时间过了一秒。

    虽然每次模拟的结果不一定相同。但对此我们不需要在意。这是由于随机数的本质导致的。我们感兴趣的是当参数改变时结果出现的趋势

    下面是一些结果:


    我们根据模拟得到了打印机在两种速度下,一小时内的任务执行情况的参考数据。可以很明显的看到,当打印质量提升后,学生平均等待时间相比低质量情况下显著增加,并且任务处理未完成的次数也出现了增加,所以设置打印机为低质量模式是最合适的。

    以上就是关于“Python的队列实例分析”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注恰卡编程网行业资讯频道。

    发布于 2022-03-09 22:50:53
    收藏
    分享
    海报
    0 条评论
    51
    上一篇:微信小程序怎么制作音乐播放器检索页 下一篇:C++智能指针shared_ptr怎么使用
    目录

      推荐阅读

      0 条评论

      本站已关闭游客评论,请登录或者注册后再评论吧~

      忘记密码?

      图形验证码