进程之间通信、线程
- 去幕布 >>
- 进程之间通信IPC机制
- 队列:先进先出(队列=管道+锁)
full、get_nowait、empty 都不适用于多进程的情况 - 队列 的方法演示
from multiprocessing import Queue q = Queue(3) # 括号内可以传参数 表示的是这个队列的最大存储数 # 往队列中添加数据 q.put(1) q.put(2) print(q.full()) # 判断队列是否满了 q.put(3) print(q.full()) # q.put(4) # 当队列满了之后,再放入数据 不会报错,会原地等待 直到队列中有数据被取走(阻塞态) print(q.get()) print(q.get()) print(q.empty()) # 判断队列中的数据是否取完 print(q.get()) print(q.empty()) # print(q.get_nowait()) # 取值 没有值不等待直接报错(queue.Empty) print(q.get()) # 当队列中的数据被取完之后,再次获取,程序会阻塞 直到有人往队列中放入值 '''执行结果 False True 1 2 False 3 True '''
- 进程间通信(IPC,InterProcess Communication)
子进程放数据,主进程获取数据
两个子进程相互 放 取数据 - IPC 之队列方式 的代码演示
from multiprocessing import Process,Queue def producer(q): q.put('hello GF~') def consumer(q): print(q.get()) if __name__ == '__main__': q = Queue() p = Process(target=producer,args=(q,)) c = Process(target=consumer, args=(q,)) p.start() c.start() '''执行结果: hello GF~ '''
- 生产者消费者模型
生产者:生产/制造数据的 消费者:消费/处理数据的 例子:做包子的,买包子的 1.做包子远比买包子的多 2.做包子的远比包子的少 供需不平衡的问题 进程中的应用: 将两个函数实例化为进程,通过队列通信, 通过JoinableQueue模块确定队列中的值是否取完
- 生产者消费者模型 在进程中的应用
from multiprocessing import Process,Queue,JoinableQueue import random import time def producer(name,food,q): for i in range(1): data = '%s生产的%s%s'%(name,food,i) time.sleep(random.random()) q.put(data) print(data) def consumer(name,q): while True: data = q.get() print('%s吃了%s'%(name,data)) time.sleep(random.random()) q.task_done() # 告诉队列你已经从队列中取出了一个数据 并且处理完毕了 if __name__ == '__main__': q = JoinableQueue() p = Process(target=producer,args=('大厨egon','馒头',q)) p1 = Process(target=producer,args=('跟班tank','生蚝',q)) c = Process(target=consumer,args=('许兆龙',q)) c1 = Process(target=consumer,args=('吃货jerry',q)) p.start() p1.start() c.daemon = True c1.daemon = True c.start() c1.start() p.join() p1.join() q.join() # 等到队列中数据全部取出 '''执行结果: 跟班tank生产的生蚝0 吃货jerry吃了跟班tank生产的生蚝0 大厨egon生产的馒头0 许兆龙吃了大厨egon生产的馒头0 Process finished with exit code 0 '''
- 队列:先进先出(队列=管道+锁)
- 线程
什么是线程 进程线程其实都是虚拟单位,都是用来帮助我们形象的描述某种事物 进程:资源单位 线程:执行单位 将内存比如成工厂 那么进程就相当于是工厂里面的车间 而你的线程就相当于是车间里面的流水线 ps:每个进程都自带一个线程,线程才是真正的执行单位,进程只是在线程运行过程中 提供代码运行所需要的资源 为什么要有线程 开进程 1.申请内存空间 耗资源 2."拷贝代码" 耗资源 开线程 一个进程内可以起多个线程,并且线程与线程之间数据是共享的 ps:开启线程的开销要远远小于开启进程的开销
- 创建线程的两种方式
# 第一种方式(直接调用Threading模块的Thread) from threading import Thread import time def task(name): print('%s is running'%name) time.sleep(3) print('%s is over'%name) # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内 t = Thread(target=task,args=('egon',)) t.start() # 告诉操作系统开辟一个线程 线程的开销远远小于进程 # 等到代码执行完,实际上线程就已经开启了 print('主') '''执行结果: egon is running 主 egon is over ''' # 第二种方式(自定义Tread方法) 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 over'%self.name) t = MyThread('egon') t.start() print('主') '''执行结果: egon is running 主 egon is over '''
- 线程对象及其他方法
from threading import Thread,current_thread,active_count import time import os def task(name,i): print('%s is running'%name) # print('子current_thread:',current_thread().name) # print('子',os.getpid()) time.sleep(i) print('%s is over'%name) # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内 t = Thread(target=task,args=('egon',1)) t1 = Thread(target=task,args=('jason',2)) t.start() # 告诉操作系统开辟一个线程 线程的开销远远小于进程 t1.start() # 告诉操作系统开辟一个线程 线程的开销远远小于进程 t1.join() # 主线程等待子线程运行完毕 print('当前正在活跃的线程数',active_count()) # 等到代码执行完 线程就已经开启了 print('主') '''执行结果: egon is running jason is running egon is over jason is over 当前正在活跃的线程数 1 主 Process finished with exit code 0 '''
- 守护线程
主线程的结束也就意味着进程的结束 主线程必须等待其他非守护线程的结束才能结束 (意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了)
- 守护线程代码示例
from threading import Thread,current_thread import time def task(i): print(current_thread().name) time.sleep(i) print('GG') t = Thread(target=task,args=(1,)) t.daemon = True t.start() print('主') '''执行结果: Thread-1 主 '''
- 线程之间通信
from threading import Thread money = 666 def task(): global money money = 999 t = Thread(target=task) t.start() t.join() print(money) '''执行结果: 999 '''
- 互斥锁在线程中的应用(将并行编程串行)
from threading import Thread,Lock import time n = 10 def task(mutex): global n mutex.acquire() tmp = n time.sleep(0.1) n = tmp - 1 mutex.release() t_list = [] mutex = Lock() for i in range(10): t = Thread(target=task,args=(mutex,)) t.start() t_list.append(t) for t in t_list: t.join() print(n) '''执行结果: 0 '''
- 创建线程的两种方式