sleep方法是time模块提供的一个中断线程运行一段时间的方法,该方法可以把当前正在运行的线程挂起一段时间(时间值由参数传入,时间单位是秒),挂起时间到期后,Python会在适当的时间再次唤醒该线程。
先看一个例子代码:
import time
import threading
class MyThread(threading.Thread):
def __init__(self,incount):
threading.Thread.__init__(self)
self.count = incount
def run(self):
r1 = range(0,self.count)
for i in r1:
print("计数: %d" % (i))
def main():
t1 = MyThread(5)
#设置线程名称
t1.setName("计数器线程");
#输出线程状态
print("线程状态:%s" % (t1.is_alive()))
#启动线程
t1.start();
# 输出线程状态
print("线程状态:%s" % (t1.is_alive()))
#中断主线程5秒
print("中断开始 : %s" % (time.ctime()))
time.sleep(5)
print("中断结束 : %s" % (time.ctime()))
#输出线程名称
print("线程名称:%s" % (t1.getName()))
if __name__ == "__main__":
main()在main方法中,主线程启动子线程后,调用time模块的sleep方法将主线程挂起5秒。在主线程挂起过程中,子线程仍然在执行,不受主线程的挂起影响。程序输出结果如下图所示:
图 1 使用sleep挂起主线程
从输出结果可以看出,主线程挂起(中断)后,主线程创建的子线程MyThread仍然在运行,主线程等待5秒后再继续执行。
上面的例子代码让我们了解了sleep的具体用法,那么sleep方法的具体应用场景是什么?实际应用编程中,在什么情况下需要使用sleep方法呢?
考虑一个编程任务。要求模拟一个文档上传服务处理程序,若干用户并发上传不同格式的文档,该服务程序需要启动一个转换线程把用户上传的文档统一转换为PDF文档。转换完成后,需要将该文档存储路径设置到文档对象中,并输出该文档信息。另外,模拟程序不需要处理实际的文档,模拟处理过程即可。
既然是并发转换文档需求,程序需要采用多线程处理。对每个用户的转换请求创建一个线程A,在线程A中,考虑到文档格式转换操作时间较长,需要创建一个转换文档格式的线程B。程序处理框架如下图所示:

图2 文档上传服务程序处理过程
用户发出上传文档请求,主服务线程接收到请求后,创建一个处理该文档的A线程。A线程启动后,创建一个文档转换线程B,B线程负责文档格式的转换工作。A线程需要等待B线程完成文档转换工作后,存储并输出文档信息。上述过程涉及到A线程和B线程的同步,A线程创建B线程后,需要等待B线程完成工作,才能继续执行。此时,A线程就可以调用sleep方法休眠一段时间,等待B线程完成工作。
(1)首先建立Document类,该类有两个属性,分别是docName、savePath,savePath属性值的设置在B线程进行。代码如下:
# 声明文档类 class Docment: # 文档类构造方法 def __init__(self, inDocName, inSavePath): self.docName = inDocName self.savePath = inSavePath def getDocName(self): return self.docName def getSavePath(self): return self.savePath def setDocName(self, inDocName): self.docName = inDocName def setSavePath(self, inSavePath): self.savePath = inSavePath
(2)建立文档转换线程类(B线程),该类通过for循环模拟长时间处理操作,并设置传入doc对象的savePath属性,表示文档转换完成。代码如下:
import threading import Document class Convert(threading.Thread): def __init__(self, inDocument): threading.Thread.__init__(self) self.doc = inDocument def run(self): #模拟长时间处理操纵 r1 = range(0, 1000) for i in r1: pass self.doc.setSavePath(self.doc.getDocName() + "_path") def getDocment(self): return self.doc
(3)建立请求处理线程类(A线程),该类启动文档转换线程,并调用sleep方法自身休眠10秒,等待文档转换工作的完成。
import threading
import Document
import Convert
import time
class Process(threading.Thread):
def __init__(self, inDocument):
threading.Thread.__init__(self)
self.doc = inDocument
def run(self):
covert = Convert.Convert(self.doc)
covert.start()
time.sleep(3)
pdoc = covert.getDocment()
if pdoc.getSavePath() == "":
pass
else:
print("%s 处理完成,存储路径为 %s \n" % (pdoc.getDocName(),pdoc.getSavePath()))
def getDocment(self):
return self.doc(4)建立主线程类,该类首先初始化文档列表,然后启动线程对每个文档进行处理。
import Document
import Process
#声明文档列表
document_list = []
def initDocument():
r1 = range(0, 5);
for i in r1:
doc = Document.Docment("文档" + str(i),"")
document_list.append(doc)
def main():
initDocument()
for i in range(len(document_list)):
doc = document_list[i]
process = Process.Process(doc)
process.start()
if __name__ == '__main__':
main() 程序输出结果如下图所示:

图 2 文档处理程序输出结果
当线程需要等待资源或者信号到达才能继续执行时,可以采用sleep方法让线程自身休眠等待资源和信号。当线程唤醒时,需要线程自身判断等待的资源是否满足或信号是否到达,当资源仍然不能满足或信号仍未到达时,需要提供一种持续等待的机制,直到资源满足或信号到达。