Python入门学习
DAY35
今日内容:
进程部分:
1. 进程间通信IPC机制
2. 生产者消费者模型
线程部分
1. 线程理论
2. 开启线程的两种方式
3. 线程对象其他相关的属性或方法
4. 守护线程
5. 线程互斥锁
进程部分:
1. 进程间通信IPC机制
Queue方法(队列)
put方法用以插入数据到队列中。put方法还有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。
get方法可以从队列读取并且删除一个元素。同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常
# 队列 : 底层就是以管道和锁定的方式实现 from multiprocessing import Queue q = Queue(3) # 创建一个队列,相当于创建了一个共享的内存空间,3表示最多可以放入3个数据 q.put(['fist']) q.put({'x':2}) q.put('abc') # q.put(4) # 当放入超过时,就会阻塞住,只有当取出一个数据时才会再次放入 print(q.get()) print(q.get()) print(q.get()) # print(q.get()) # 当队列中数据取完后再取也会阻塞住,直到下一个数据传入再取出
2. 生产者消费者模型
什么是生产者消费者模型
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,
如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.
因此,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式
为什么要用生产者消费者模型
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
基于队列实现生产者消费者模型
import time,random from multiprocessing import Process,JoinableQueue def producer(name,food,q): for i in range(3): res = '%s%s' %(food,i) time.sleep(random.randint(1,3)) # 模拟生产时间 q.put(res) print('厨师[%s]生产了<%s>'%(name,res)) def consumer(name,q): while True: res = q.get() time.sleep(random.randint(1,3)) # 模拟处理数据的时间 print('吃货[%s]吃了<%s>'%(name,res)) q.task_done() if __name__ == '__main__': q = JoinableQueue() # 生产者 p1 = Process(target = producer,args = ('厨师1','佛跳墙',q)) p2 = Process(target = producer,args = ('厨师2','灌汤包',q)) p3 = Process(target = producer,args = ('厨师3','酸菜鱼',q)) # 消费者 c1 = Process(target = consumer,args = ('顾客1',q)) c2 = Process(target=consumer,args = ('顾客2',q)) c1.daemon = True c1.daemon = True p1.start() p2.start() p3.start() c1.start() c2.start() p1.join() p2.join() p3.join() q.join() # 主进程等q结束,即q内数据被取干净了 print('主进程')
生产者消费者模型总结
程序中有两类角色
一类负责生产数据(生产者)
一类负责处理数据(消费者)引入生产者消费者模型为了解决的问题是:
平衡生产者与消费者之间的工作能力,从而提高程序整体处理数据的速度如何实现:
生产者<—>队列<—>消费者
生产者消费者模型实现类程序的解耦和
线程部分
线程理论什么是线程
进程其实一个资源单位,而进程内的线程才是cpu上的执行单位
线程其实指的就是代码的执行过程为何要用线程
线程和进程
同一进程下的多个线程共享该进程内的资源
创建线程的开销要远远小于进程
开启线程的两种方式
方式一:
from threading import Thread import time,os def task(name): print(os.getpid()) print('%s is running '%name) time.sleep(2) print('%s is done '%name) if __name__ == '__main__': t = Thread(target=task,args=('线程1',)) t.start() print('主线程',os.getpid())
方式二:
from threading import Thread import time class Mythread(Thread): def run(self): print('%s is running '%self.name) time.sleep(2) print('%s is done' % self.name) if __name__ == '__main__': t = Mythread() t.start() print('主线程')
线程对象其他相关的属性或方法
Thread实例对象的方法 # isAlive(): 返回线程是否活动的。 # getName(): 返回线程名。 # setName(): 设置线程名。 threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程变量。 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
守护线程
from threading import Thread import time def task(name): print('%s is running' %name) time.sleep(2) print('%s is done' %name) if __name__ == '__main__': t=Thread(target=task,args=('线程1',)) t.daemon=True t.start() print('主')
线程互斥锁
from threading import Thread,Lock import time mutex = Lock() 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)
以上为本次学习内容