更简单的线程池:python
多线程和多进程均可以很容易的实现并发,协程经过切换上下文来充分利用cpu实现并发效果
threading模块
多线程
Thread类的基本状态和行为
属性名和值:并发
name=None,group=None,target=None,args=(),kwargs={},daemon=None
方法:异步
start(),join(),run(), join()
使主线程等待使用join()方法的子进程结束,不然阻塞本身 ,
Thread中的子进程默认daemon就是None,这意味着子进程不结束,主进程也不结束,说明主进程是个好大哥,
而thread模块开启的子进程就没这个命,主进程结束,子进程跟着完蛋。
join()方法:
效果 :使主线程等待使用join()方法的子线程结束,不然阻塞本身 ,
使用场景:主线程须要接受子线程的计算结果时使用
守护线程是指不重要的进程,若是Thread实例化子进程的时候将其设置成守护进程,主线程结束时,将结束子线程。函数
子进程的建立与运行,分为三种方式,测试
-实例化Thread,target=自定义函数ui
-实例化Thread,target=自定义类,start()这个实例时,自动调用自定义类的__call__()方法,因此,自定义类必需要自定义__call__()方法。spa
-自定义建立一个Thread的派生子类,而后自定义其run()方法,而后实例化这个类,而后调用其start()方法,
-须要注意,实例化子进程使用一次,不能再次调用start()方法线程
主要使用第一种方法,和第三种方法code
给出第三种方法的例子
import time, threading import threading,time class Mythread(threading.Thread): def __init__(self,args): threading.Thread.__init__(self) self.args=args def do_1(self): print('我是do_1 我是作好事') def do_2(self): print('我是do_2 我是作傻事') def do_3(self): print('我是do_3 我是作坏事') def run(self): time.sleep(1) if self.args % 3==0: self.do_1() if self.args % 3==1: self.do_2() if self.args % 3==2: self.do_3() if __name__ == '__main__': for i in range(20): t = Mythread(i) t.start() print('大哥已经完事,等小弟们') 运行结果:
大哥已经完事,等小弟们
我是do_2 我是作傻事
我是do_1 我是作好事
我是do_3 我是作坏事
我是do_1 我是作好事
我是do_2 我是作傻事
我是do_3 我是作坏事
我是do_1 我是作好事
我是do_1 我是作好事
我是do_2 我是作傻事
我是do_2 我是作傻事
我是do_3 我是作坏事
我是do_1 我是作好事
我是do_3 我是作坏事
我是do_2 我是作傻事
我是do_3 我是作坏事
我是do_2 我是作傻事
我是do_1 我是作好事
我是do_2 我是作傻事
我是do_3 我是作坏事
我是do_1 我是作好事
类方法:
active_count():存活的线程数量,能够用来控制同时存活并发线程数目。通过测试,win10,i7四核线程能够同时发起几千个线程,固然这没有必要。
current_thread():返回当前环境的Thread对象,数据类型int
enumerate():返回活动的Thread对象列表,数据类型list
[<_MainThread(MainThread, started 28388)>, <Mythread(Thread-1, started 21276)>, <Mythread(Thread-2, started 29028)>, <Mythread(Thread-3, started 29528)>, <Mythread(Thread-4, started 19448)>, <Mythread(Thread-5, started 26416)>, <Mythread(Thread-6, started 22084)>, <Mythread(Thread-7, started 31032)>, <Mythread(Thread-8, started 24824)>, <Mythread(Thread-9, started 14076)>, <Mythread(Thread-10, started 31076)>, <Mythread(Thread-11, started 22516)>, <Mythread(Thread-12, started 30032)>, <Mythread(Thread-13, started 22836)>, <Mythread(Thread-14, started 19340)>, <Mythread(Thread-15, started 27456)>, <Mythread(Thread-16, started 31292)>, <Mythread(Thread-17, started 26192)>, <Mythread(Thread-18, started 22444)>, <Mythread(Thread-19, started 25536)>, <Mythread(Thread-20, started 30204)>]
setprofile(func):为全部进程设置一个trace函数
setprofile(func):为全部线程设置一个profile函数
stack_size(size=0):返回新建立线程的栈大小,设定以后建立线程的栈大小
锁和信号量,控制数据访问
信号量用来控制并发子线程的数量,使其不至于访问过快,
信号量是一个计数器 设置它的最大值,最小值不设置,为0,
bignumber=BoundedSemaphore(5) 表明最大数字是5,每一次bignumber.acquire()使数字减一,
bigunmber.release()使数字加一 当数字小于0,或者大于5时阻塞。
acquire()和release方法参数: acquire(self, blocking=True, timeout=None):
register函数
-对主进程运行时间的控制,
- 在子进程异步执行同时,主程序后续执行依赖子程序的返回结果
join(),atexit模块register。
实现较为精细的控制:join方法经过注册每个子线程,当即阻塞主线程
粗暴的控制:
from atexit import register #在当前函数租册一个退出函数,当前函数退出的时候执行 @register def _atexit(): #.... 写入文件,输出最终结果 #注意:能够在任意一层函数设置