一、进程补充
1.进程间通信(IPC机制)
进程间通讯有两种方法:管道或者队列。
1 队列和管道都是将数据存放于内存中
2 队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来。
from multiprocessing import Queue q=Queue(3)#3是队列允许存在的个数 q.put('1') q.put('2') q.put('3') print(q.get(block=True,timeout=2)) print(q.get()) print(q.get())
block默认是True,意思是可以阻塞。timeout是阻塞时间,阻塞时间到了会报错
那么什么情况下会阻塞:
1.当限制队列里的数量时,放入超过限制的消息,会阻塞,等待第一个放入的被取走,才会继续执行
2.当限制队列里的数量时,取出超过限制的消息,因为此时的队列是空的,只有队列里再次放入内容时才会继续执行
2.生产者消费者模型
1. 什么是生产者消费者模型
生产者:代指生产数据的任务
消费者:代指处理数据的任务
该模型的工作方式:
生产生产数据传递消费者处理
实现方式:
生产者---->队列<------消费者
2. 为何要用
当程序中出现明细的两类任务,一类负责生产数据,一类负责处理数据
就可以引入生产者消费者模型来实现生产者与消费者的解耦合,平衡生产能力与消费能力,从提升效率
3. 如何用
from multiprocessing import Process,Queue import time,random def producer(name,food,p): for i in range(3): res='%s%s'%(food,i) time.sleep(random.randint(1,3)) print('%s生产了%s'%(name,res)) p.put(res) def customer(name,p): while True: res=p.get() if res is None:break#判断消费者是否消费完,如果消费完,就会取到NONE time.sleep(random.randint(1,3)) print('%s吃了%s'%(name,res)) if __name__ == '__main__': p=Queue() p1=Process(target=producer,args=('1','葱油拌屎',p,)) p2 = Process(target=producer, args=('2', '手抓屎', p,)) p3 = Process(target=producer, args=('3', '飘香拌屎', p,)) c1=Process(target=customer,args=('姚晓锋',p,)) c2 = Process(target=customer, args=('阿飞', p,)) p1.start() p2.start() p3.start() c1.start() c2.start() p1.join() p2.join() p3.join()#说明此时生产者已经生产完了 p.put(None)#有几个消费者就加上几个NONE p.put(None) c1.join() c2.join() print('主')
from multiprocessing import Process,JoinableQueue import time,random def producer(name,food,p): for i in range(3): res='%s%s'%(food,i) time.sleep(random.randint(1,3)) print('%s生产了%s'%(name,res)) p.put(res) def customer(name,p): while True: res=p.get() time.sleep(random.randint(1,3)) print('%s吃了%s'%(name,res)) if __name__ == '__main__': p=JoinableQueue() p1=Process(target=producer,args=('1','葱油拌屎',p,)) p2 = Process(target=producer, args=('2', '手抓屎', p,)) p3 = Process(target=producer, args=('3', '飘香拌屎', p,)) c1=Process(target=customer,args=('姚晓锋',p,)) c2 = Process(target=customer, args=('阿飞', p,)) c1.daemon=True c2.daemon=True p1.start() p2.start() p3.start() c1.start() c2.start() p1.join() p2.join() p3.join() p.join()#主进程等待队列里为空 #一旦队列为空,说明消费者取完了队列,消费者没有价值了 print('主')
二、线程理论
1 什么是线程
进程其实一个资源单位,而进程内的线程才是cpu上的执行单位
线程其实指的就是代码的执行过程
2 为何要用线程
线程的优点
1. 同一进程下的多个线程共享该进程内的资源
2. 创建线程的开销要远远小于进程
三、开启线程的两种方式
线程开启的方式与进程一致
from threading import Thread import time def task(name): print('%s is running'%name) time.sleep(3) print('%s is done'%name) if __name__ == '__main__': p=Thread(target=task,args=('yxf',)) p.start() print('主')
from threading import Thread import time class Mythread(Thread): def __init__(self,name): super().__init__() self.name=name def run(self): print('%s is running'%self.name) time.sleep(3) print('%s is done'%self.name) if __name__ == '__main__': p=Mythread('egon') p.start() print('主')
四、线程特性介绍
Thread实例对象的方法
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
threading模块提供的一些方法
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
同一进程下的线程共享资源
from threading import Thread,current_thread,active_count n=100 def task(): global n n=0 print('子进程n=',n,current_thread()) if __name__ == '__main__': p1=Thread(target=task,) p1.start() print(active_count()) p1.join() print(active_count()) print('主进程n=',n,current_thread())
五、守护线程
守护线程的生命周期取决于被守护线程(主线程)的生命周期,但是主线程要等到非守护线程都结束执行才会执行完毕
也就是说,只有非守护线程都执行完毕,守护线程才会结束
from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") if __name__ == '__main__': t1=Thread(target=foo) t2=Thread(target=bar) t1.daemon=True t1.start() t2.start() print("main-------")
六、线程互斥锁
与进程一致
from threading import Thread,Lock import time mutex=Lock() n=100 def task(): global n mutex.acquire() temp=n time.sleep(0.1) n=temp-1 mutex.release() if __name__ == '__main__': t_l=[] for i in range(100): t=Thread(target=task) t_l.append(t) t.start() for t in t_l: t.join() print(n)