博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
threading模块
阅读量:6874 次
发布时间:2019-06-26

本文共 6134 字,大约阅读时间需要 20 分钟。

#更高级别的threading不仅提供了Thread类,还提供了各种非常好用的同步机制。
#_thread模块不支持守护线程,当主线程退出时,所有子线程无论是否在工作,都会被强制退出。threading模块支持守护线程,守护线程一般时一个等待客户请求的服务器,如果没有客户提出请求,就一直等着。如果设定一个线程为守护线程,就表示这个线程不重要,在进程退出时,不用等待这个线程退出。如果主线程退出时不用等待子线程完成,就要设定这些线程的daemon属性,即在线程Thread.start()开始前,调用setDaemon()函数设定线程的daemon标志(Thread.setDaemon(True)),表示这个线程“不重要”,如果一定要等待子线程执行完成再退出主线程,就什么都不用做或显式调用Thread.setDaemon(False)以保证daemon标志为False,可以调用Thread.isDaemon()函数判断daemon标志的值。新的子线程会继承父线程的daemon标志,整个Python在所有非守护线程退出后才会结束,即进程中没有非守护线程存在时才会结束。
 
threading的thread类
#Thread有很多_thread模块里没有的函数,Thread对象的函数很丰富。下面创建一个Thread的实例,传给他一个函数。示例如下:
1 #!/usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #threading的thread类 4  5 import threading 6 from time import sleep 7 from datetime import datetime 8  9 loops=[4,2]10 date_time_format='%y-%M-%d %H:%M:%S'11 12 def date_time_str(date_time):13     return datetime.strftime(date_time,date_time_format)14 15 def loop(n_loop,n_sec):16     print('线程(',n_loop,')开始执行:',date_time_str(datetime.now()),',先休眠(',n_sec,')秒')17     sleep(n_sec)18     print('线程(',n_loop,')休眠结束,结束于:',date_time_str(datetime.now()))19 20 def main():21     print('---所有线程开始执行:',date_time_str(datetime.now()))22     threads=[]23     n_loops=range(len(loops))24 25     for i in n_loops:26         t=threading.Thread(target=loop,args=(i,loops[i]))27         threads.append(t)28 29     for i in n_loops:        #start threads30         threads[i].start()31 32     for i in n_loops:        #wait for all33         threads[i].join()    #thread to finish34 35     print('---所有线程执行结束于:',date_time_str(datetime.now()))36 37 if __name__=='__main__':38     main()
#执行结果如下:
1 D:\Pythonworkspace>python threading_thread.py2 ---所有线程开始执行: 18-31-30 09:31:543 线程( 0 )开始执行: 18-31-30 09:31:54 ,先休眠( 4 )秒4 线程( 1 )开始执行: 18-31-30 09:31:54 ,先休眠( 2 )秒5 线程( 1 )休眠结束,结束于: 18-31-30 09:31:566 线程( 0 )休眠结束,结束于: 18-31-30 09:31:587 ---所有线程执行结束于: 18-31-30 09:31:58
#由执行结果我们看到,实例化一个Thread(调用Thread())与调用_thread.start_new_thread()最大的区别是新的线程不会立即开始。创建线程对象却不想马上开始运行线程时,Thread是一个很有用的同步特性。所有线程都创建之后,再一起调用start()函数启动,而不是每创建一个线程就启动。而且不用管理一堆锁的状态(分配锁、获得锁、释放锁、检查锁的等状态),只要简单对每个线程调用join()主线程,等待子线程结束即可。join()还可以设置timeout参数,即主线程的超时时间。
#join()的另一个比较重要的方面是可以完全不用调用。一旦线程启动,就会一直运行,直到线程的函数结束并退出为止。如果主线程除了等线程结束外,还有其他事情要做,就不用调用join(),只有在等待线程结束时才调用。
#我们再看示例,创建一个Thread的实例,并传给它一个可调用的类对象。代码如下:
1 #!/usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #threading_join() 4  5 import threading 6 from time import sleep 7 from datetime import datetime 8  9 loops=[4,2]10 date_time_format='%y-%M-%d %H:%M:%S'11 12 class ThreadFunc(object):13     def __init__(self,func,args,name=''):14         self.name=name15         self.func=func16         self.args=args17 18     def __call__(self):19         self.func(*self.args)20 21 def date_time_str(date_time):22     return datetime.strftime(date_time,date_time_format)23 24 def loop(n_loop,n_sec):25     print('线程(',n_loop,')开始执行:',date_time_str(datetime.now()),',先休眠(',n_sec,')秒')26     sleep(n_sec)27     print('线程(',n_loop,')休眠结束,结束于:',date_time_str(datetime.now()))28 29 def main():30     print('---所有线程开始执行:',date_time_str(datetime.now()))31     threads=[]32     nloops=range(len(loops))33 34     for i in nloops:35         t=threading.Thread(target=ThreadFunc(loop,(i,loops[i]),loop.__name__))36         threads.append(t)37 38     for i in nloops:     #start all threads39         threads[i].start()40 41     for i in nloops:    #wait for completion42         threads[i].join()43 44     print('---所有线程执行结束于:',date_time_str(datetime.now()))45 46 if __name__=='__main__':47     main()
#执行结果如下:
1 D:\Pythonworkspace>python threading_join().py2 ---所有线程开始执行: 18-30-30 11:30:263 线程( 0 )开始执行: 18-30-30 11:30:26 ,先休眠( 4 )秒4 线程( 1 )开始执行: 18-30-30 11:30:26 ,先休眠( 2 )秒5 线程( 1 )休眠结束,结束于: 18-30-30 11:30:286 线程( 0 )休眠结束,结束于: 18-30-30 11:30:307 ---所有线程执行结束于: 18-30-30 11:30:30
#由执行结果看到,与传一个函数很相似的一个方法是,在创建线程时,传一个可调用的类的实例供线程启动时执行,这是多线程编程的一个面向对象的方法。相对于一个或多个函数来说,类对象可以使用类的强大功能。创建线程时,Thread对象会调用ThreadFunc对象,这时会用到一个特殊函数__call__()。由于已经有了要用的参数,因此不用再传到Thread()的构造函数中。对于一个参数的元组,要使用self.func(*self.args)方法。
#从Thread派生一个子类,创建这个子类的实例,从上面的代码派生的代码如下:
1 #!/usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #threading___call__ 4  5 import threading 6 from time import sleep 7 from datetime import datetime 8  9 loops=[4,2]10 date_time_format='%y-%M-%d %H:%M:%S'11 12 class MyThread(threading.Thread):13     def __init__(self,func,args,name=''):14         threading.Thread.__init__(self)15         self.name=name16         self.func=func17         self.args=args18 19     def getResult(self):20         return self.res21 22     def run(self):23         print('starting',self.name,'at:',date_time_str(datetime.now()))24         self.res=self.func(*self.args)25         print(self.name,'finished at:',date_time_str(datetime.now()))26 27 def date_time_str(date_time):28     return datetime.strftime(date_time,date_time_format)29 30 def loop(n_loop,n_sec):31     print('线程(',n_loop,')开始执行:',date_time_str(datetime.now()),',先休眠(',n_sec,')秒')32     sleep(n_sec)33     print('线程(',n_loop,')休眠结束,结束于:',date_time_str(datetime.now()))34 35 def main():36     print('---所有线程开始执行:',date_time_str(datetime.now()))37     threads=[]38     n_loops=range(len(loops))39 40     for i in n_loops:41         t=MyThread(loop,(i,loops[i]),loop.__name__)42         threads.append(t)43 44     for i in n_loops:45         threads[i].start()46 47     for i in n_loops:48         threads[i].join()49 50     print('---所有线程执行结束于:',date_time_str(datetime.now()))51 52 if __name__=='__main__':53     main()
#执行结果如下:
1 D:\Pythonworkspace>python threading_call.py 2 ---所有线程开始执行: 18-12-30 15:12:55 3 starting loop at: 18-12-30 15:12:55 4 线程( 0 )开始执行: 18-12-30 15:12:55 ,先休眠( 4 )秒 5 starting loop at: 18-12-30 15:12:55 6 线程( 1 )开始执行: 18-12-30 15:12:55 ,先休眠( 2 )秒 7 线程( 1 )休眠结束,结束于: 18-12-30 15:12:57 8 loop finished at: 18-12-30 15:12:57 9 线程( 0 )休眠结束,结束于: 18-12-30 15:12:5910 loop finished at: 18-12-30 15:12:5911 ---所有线程执行结束于: 18-12-30 15:12:59
#由代码片段和执行结果我们看到,子类化Thread,MyThread子类的构造函数一定要先调用基类的构造函数,特殊函数__call__()在子类中,名字要改为run()。在Thread类中,加入一些用于调试的输出信息,把代码保存到MyThread模块中,并导入这个类。使用self.func()函数运行这些函数,并把结果保存到实现的self.res属性中,创建一个新函数getResult()得到结果。

转载于:https://www.cnblogs.com/DLHe/p/8411242.html

你可能感兴趣的文章
041 SparkSql的回顾与复习
查看>>
myql基准测试工具Sysbench
查看>>
想拥有一款钢铁侠Jarvis管家的软件吗?
查看>>
web前端自动化测试利器puppeteer介绍
查看>>
Mac怎么生成.ssh文件
查看>>
“C语言” 读书札记(四)之[再续编译执行]
查看>>
[CODE] Dahua Lin贡献的两个开源软件
查看>>
高斯消元法求解线性方程组的解集
查看>>
C++ 沉思录——Chap5:代理类
查看>>
通向架构师的道路(第一天)之Apache整合Tomcat - lifetragedy的专栏 - 博客频道 - CSDN.NET...
查看>>
VS2015 android 设计器不能可视化问题解决。
查看>>
httppp 1.4.0 发布,HTTP响应时间监控
查看>>
52. N-Queens II
查看>>
【Mongodb】3.X 配置身份验证
查看>>
云计算就像马拉松 京东CTO为啥这么说
查看>>
「每天一道面试题」Java虚拟机为新生对象分配内存有哪两种方式?
查看>>
海信电器于芝涛:坚守画质 才是消费者首选
查看>>
直播竞答必读:一定要提前知道的技术坑和新玩法
查看>>
React 中集成 Markdown编辑器
查看>>
Spring Boot 最佳实践(五)Spring Data JPA 操作 MySQL 8
查看>>