# -*- coding=utf-8 -*- # v150710_1 by PosPro # please visit: http://blog.csdn.net/pospro ## 基于Python内置的list,实现先入先出(FIFO)的队列 class Queue: def __init__(self): self.qList=[] def enqueue(self, data): self.qList.append(data) ## 向队列添加数据,复杂度为O(1) def dequeue(self): return self.qList.pop(0) ## 删除数据复杂度O(n) def isEmpty(self): return self.qList==[] def size(self): return len(self.qList) def __str__(self): return self.qList.__str__() '''以下部分仅作测试之用 q = Queue() q.enqueue('hello') print q q.enqueue('dog') print q q.enqueue(3) print q q.dequeue() print q q.enqueue('cat') print q print str(q.size()) q.dequeue() print q print q.isEmpty() q.dequeue() print q '''
由于每一个任务所对应的页数是不一样的,所以在startTask时,需要一个输入参数Task,Task本身将给出具体的页数。
# -*- coding=utf-8 -*- # v150710_1 by PosPro # please visit: http://blog.csdn.net/pospro ## 建立一个可以用于模拟的Printer from Queue import Queue class Printer: def __init__(self, pagesPerMinute): self.ppm=pagesPerMinute self.isWorking=False self.timeRemaining=0 def isBusy(self): return self.isWorking def startTask(self, task): self.isWorking=True self.timeRemaining=task.getPages()*60/self.ppm ## 上句得出的是新任务需要多少秒后才能完成, 60带来的是从分钟到秒的变换 ##这个函数是模拟器工作的关键,它将1次循环和1秒对应了起来 def tick(self): if self.timeRemaining>0: self.timeRemaining-=1 if self.timeRemaining<=0: self.timeRemaining=0 self.isWorking=False
# -*- coding=utf-8 -*- # v150710_1 by PosPro # please visit: http://blog.csdn.net/pospro ## 建立一个可以随机生成打印页数的Task, 该Task同时还记录了任务产生时的时间戳 import random class Task: def __init__(self, time): self.pages=random.randrange(1,21) ## 生成1~20的随机页数 self.timestamp=time def getPages(self): return self.pages def getTimestamp(self): return self.timestamp def waitTime(self, currentTime): return currentTime-self.timestamp
# -*- coding=utf-8 -*- # v150710_1 by PosPro # please visit: http://blog.csdn.net/pospro ## 以一个3600次的循环模拟一小时中的3600秒,在每一个循环(每一秒), ## 以此驱动打印任务的产生,打印任务的执行。在循环结束后汇总分析 import random from Queue import Queue from Printer import Printer from Task import Task ''' isNewTaskEmerge(),是一个辅助函数,其原理如下: 因为题目中的描述是,每个小时最多有10位学生在图书馆, 他们在一小时终最多提交2次打印任务。 换而言之,一小时内最多有20次任务,也即180秒内可能产生1次任务。 但是产生任务的具体时间是随机的,所以这个辅助函数在每秒钟抽取一下1~180之间的随机数, 如果等于某个特定值就认为有新任务产生 这个特定值具体是多少无关紧要,只要在180以内,在某个特定秒,概率都是1/180。 本例中取11。 ''' def isNewTaskEmerge(): randoNum=random.randrange(1,181) if randoNum==11: return True ## 此时将产生一个新任务 else: return False def Simulator(totalTime, pagesPerMinute): libraryPrinter=Printer(pagesPerMinute) printTaskQueue=Queue() # 保存所有生成的Task waitingTime=[] #以一个队列保存所有Task的等待时间 for t in range(totalTime): ##totalTime就是测试的总时间,循环一次是1秒 if isNewTaskEmerge(): newTask=Task(t) #传入当前时间t作为时间戳 printTaskQueue.enqueue(newTask) if libraryPrinter.isBusy(): libraryPrinter.tick() #如果打印机当前有任务,则继续工作 else: if not printTaskQueue.isEmpty(): nextTask=printTaskQueue.dequeue() waitingTime.append(nextTask.waitTime(t)) #传入当前时间以便计算在该任务在队列中的等待时间 libraryPrinter.startTask(nextTask) avgWaitTime=sum(waitingTime)/len(waitingTime) print "Average Wait %6.2f secs %3d tasks remaining."%(avgWaitTime, printTaskQueue.size()) ## 以下代码启动测试程序 print "=== Mode 5 pages/min =====" for i in range(10): #每种工作模式测试10次 Simulator(3600, 5) print print "=== Mode 10 pages/min =====" for i in range(10): #每种工作模式测试10次 Simulator(3600, 10)