一、多线程的创建(threading关键字):定义一个就启动一个,适合IO多的操作
方法一:创建函数,将函数名传入到threading.Thread(target = 函数名,args = (传入的实参,))
方法二:创建一个类继承threading.Thread,重写run方法,传参重写init方法,但是要调用父类的init方法
互斥锁: 创建锁— mutex_lock = threading.lock()
上锁— mutex_lock.acquire() (请求锁)
解锁— mutex_lock.release()
二、多进程的创建(multiprocessing关键字):定义一个就启动一个,适合CPU密集型操作
方法一:创建函数,将函数名传入multiprocess.Process(target=函数名,args=(参数,))
方法二:继承multiprocessing.Process类,重写run方法,传参重写init方法,但要调用父类的init方法
通信:multiprocessing.Queue()
三、进程池(重复使用进程,控制进程的数量,减少内存开销):这样创建一次:pool = multiprocessing.Pool(processes=3);这样循环使用(空闲的进程会派出去):pool.apply_async(func=worker, args=(i,))
创建:multiprocessing.Pool() 计算机的核数
执行任务:pool.apply_async(func=目标函数名,args=(参数,), kwds={})
关闭进程池:pool.close()
阻塞主进程:pool.join()
通信:multiprocessing.Manage().Queue()
四、协程(遇到了耗时操作就不等,主进程不等协程,所以要打补丁来启动协程并进行轮训) 参数只能一个一个传递过去:启动:g1 = gevent.spawn(函数名,参数1,参数2);阻塞:g1.join()
1、for...in....和next(迭代器有相同的效果)
2、创建协程:yield 要有循环 w1 = worker1() worker1():生成器,w1迭代器
3、创建协程:关键字:gevent ---封装了greenlet
import gevent
from gevent import monkey # 打补丁
monkey.patch_all()
gevent.spawn(函数名,参数1,参数2) # 不用join,打了补丁spawn就会轮训
总结:1、都可以通过绑定函数名来实现多任务,线程、进程用target参数,进程池用func参数;协程直接函数名gevent.spawn(函数名,参数)
2、线程、进程、进程池传参有args(元组)和kwargs(字典),而协程只能一个一个传
3、主线程、主进程会等待子线程、子进程执行完,但是主进程不等进程池里面的进程执行完,所以要pool.close(),pool.join(),主进程也不等协程,gevent.joinall
4、进程、线程都要start启动,进程池:pool.close()、pool.join(),协程:gevent.joinall([]) 或打补丁后gevent.spawn(函数名,参数1,参数2)
5、多进程、进程池不共享全局变量,通信分别用multiprocessing.Queue()、multiprocess.Manage().Queue();多线程共享全局变量(互斥锁);协程共享全局变量。