今日主要内容:

1.管道(Pipe) 数据接收一次就没有了

2.事件(Event)

3.基于事件的进程通信

4.信号量(Semaphore)

5. 进程池(重点)

6.进程池的同步方法和异步方法

7. 进程池的回调函数,( pool.apply_async(f1,args=(1,),callback=f2) ) ,回调函数是在异步进程中的函数

1.管道(Pipe) 数据接收一次就没有了

Pipe() #创建管道,全双工,返回管道的两端,但是一端发送消息,只能是另一端才能接受到,自己这一端是接收不到的

from multiprocessing import Process,Pipe
def f1(conn):
from_zhujincheng=conn.recv()# 此处接收可以接收任何数据,而且不需要带最大的传输的大小
print('我是子进程')
print('来自主进程的消息>>>',from_zhujincheng)

if __name__=='__main__':
conn1,conn2=Pipe() # 创建管道,全双工,返回管道的两端,但是一端发送的消息,只能另一端接收,自己这一端是不能接受的
# 可以将一端或者两端发送给其他的进程,那么多个进程之间就可以通过这一个管道进行通信了 但是这样会导致数据的不安全,容易导致程序错乱

p1=Process(target=f1,args=(conn1,) )
p1.start()
conn2.send('你好啊,大兄嘚')
print('我是主进程')

2.事件(Event)

Event() #创建事件对象,这个对象的初始状态为False

from multiprocess import Process,Event

e=Event() # 创建事件对象,这个对象的初始状态为False
print('判断e的状态>>>' , e.is_set()) #判断e当前的状态
print('程序运行到这里了')
e.set() # 这里的作用是将对象的状态改为True
e.clear() # 将e的状态改为False
e.wait() # 如果程序中e的状态为False,那么系统会阻塞在这里,只有改为True的时候才会继续往下执行
print('进程走过了wait.')

3.基于事件的进程通信
import time
from multiprocessing import Process,Event

def func(e):
time.sleep(1)
n=100
print('子进程计算结果为',n)
e.set() # 将e的值修改为True

if __name__=='__main__':
e=Event() # 创建事件对象,初始状态为False
p=Process(target=func,args=(e,))
p.start()

print('主程序在等待中......')
e.wait() # 等待e的值变为True
print('结果执行完毕,可以拿到这个值')

4.信号量(Semaphore)

S = semphore(4),内部维护了一个计数器,acquire-1,release+1,为0的时候,其他的进程都要在acquire之前等待
S.acquire()
需要锁住的代码
S.release()

Semaphore(4) # 计数器4,acquire一次减一,如果semaphore的值为0,其他人等待,release加一 . 抢票啊啥的一般用这个,就是多个程序抢占这4个cpu,如果4个都被占用了,那么他们剩余的全部等待,只有当一个人执行完毕的时候,剩下的人才会继续争抢这个cpu.

import time
import random
from multiprocessing import Process,Semaphore
def func():
s.acquire() # 与进程锁的用法类似
print(f'{i}号男嘉宾登场')
time.sleep(random.randint(1,3)) # 随机
s.release() #与进程锁的用法类似
if __name__=='__main__':
s=Semaphore(3) # 计数器3,每当acquire一次,计数器就减一,当release一次,计数器就加一. 如果计数器为0,那么意味着所有的计数器都被占用,其他的程序都要等待这3个程序,如果一个执行完毕后,剩下的才可以继续争抢这个名额.
for i in range(10): # 创建了10个进程,
p=Process(target=func,args=(i,))
p.start()

5. 进程池(重点)

进程的创建和销毁是很有消耗的,影响代码执行效率
进程池:
Map:异步提交任务,并且传参需要可迭代类型的数据,自带close和join功能
Res = Apply(f1,args=(i,)) #同步执行任务,必须等任务执行结束才能给进程池提交下一个任务,可以直接拿到返回结果res

Res_obj = Apply_async(f1,args=(i,)) #异步提交任务,可以直接拿到结果对象,从结果对象里面拿结果,要用get方法,get方法会阻塞程序,没有拿到结果会一直等待

Close : 锁住进程池,防止有其他的新的任务在提交给进程池
Join : 等待着进程池将自己里面的任务都执行完

回调函数:
Apply_async(f1,args=(i,),callback=function) #将前面f1这个任务的返回结果作为参数传给callback指定的那个function函数

进程池的map用法 (Pool)

# 对比多进程和进程池的效率,统计进程池和多进程执行100个任务的时间
import time
from multiprocessing import Process,Pool
def func(i):
time.sleep(0.5)
for a in range(10):
n=n+i

if __name__=='__main__':
# 进程池执行100个任务的时间
s_time=time.time()# 记录开始的时间
p=Pool(4) # 里面的参数是指定进程池中有多少个进程用的,4表示4个进程,如果不传参数,那么默认开启的进程数就是你电脑的cpu个数
p.map(func,range(100)) # map 2个参数第一个是你要执行的函数,第二个必须是可迭代的 ,异步提交任务,自带join功能
e_time=time.time()# 记录结束的时间
res_time=e_time-s_time
print('进程池执行命令所用时间>>>',res_time)

#多进程执行100个任务的时间
p_s_t=time.time()
p_list=[]
for i in range(100):
p=Process(target=func,args=(i,))
p.start()
p_list.append(p)

[pp.join() for pp in p_list]
p_e_t=time.time()

res_t = p_e_t - p_s_t

print('多进程执行命令所用的时间>>>',res_t)

# 结果
进程池执行命令所用时间:0.40s
多进程执行命令所用时间:9.24s
所以说进程池的时间比多进程的时间快了近十倍,所以......你懂我的意思吧,兄嘚

6.进程池的同步方法和异步方法
apply() 同步方法,将任务变成了串行
apply_async()异步方法

# 同步方法
import time
from multiprocessing import Process,Pool
def func(n):
time.sleep(1)
# print(n)
return n*n

if __name__=='__main__':
po=Pool(4)
for i in range(10):
print('你好啊,大哥')
res=po.apply(func,args=(i,)) #进程池的同步方法,将任务变成了串行
print(res)

#异步方法
import time
from multiprocessing import Process,Pool

def func():
pass

if __name__=='__main__':
po=Pool(4)
p_list=[]
for i in range(10):
print('你能每次都看到我吗?')
res=po.apply_async(func,args=(i,)) #异步给进程池提交任务
p_list.append(res)

po.close()#锁住进程池,意思就是不让其他的长须再往这个进程池里面提交任务了
po.join() # 必须等待子程序执行完毕才可以执行主程序

#打印结果,如果异步提交之后的结果对象
for i in p_list:
print(i.get())# 从对象中拿值需要用到get方法,get的效果是join的效果
# 主程序运行结束,进程池里面的任务全部停止,不会等待进程池里面的任务
print('主进程直接结束')

7. 进程池的回调函数,( pool.apply_async(f1,args=(1,),callback=f2) ) ,回调函数是在异步进程中的函数

所谓的回调函数其实指的是,在主进程中第一个函数算出的值,被回调函数把结果传入到第二个函数中进行计算.

import os
from multiprocess import Process,Pool

def func(n):
s=n+1
return s**2

def func2(x):
print('回调函数中的结果>>>',x)

if __name__=='__main__':
po=Pool(4)
po.apply_async(func,args=(3,),callback=func2)
po.close()
po.join()

print('主进程的id',os.getpid())

day32 信号量 事件 管道 进程池的更多相关文章

  1. GIL与普通互斥锁区别,死锁现象,信号量,event事件,进程池与线程池,协程

    GIL与普通互斥锁区别 GIL锁和互斥锁的异同点 相同: 都是为了解决解释器中多个线程资源竞争的问题 异: 1.互斥锁是Python代码层面的锁,解决Python程序中多线程共享资源的问题(线程数据共 ...

  2. day31 管道 进程池 数据共享

    1.    管道(了解) #创建管道的类: Pipe([duplex]):在进程之间创建一条管道,并返回元组(conn1,conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须 ...

  3. Manager模块 队列 管道 进程池

    Manager模块 作用:  多进程共享变量. Manager的字典类型: 如果value是简单类型,比如int,可以直接赋值给共享变量,并可以后续直接修改 如果value是复杂类型 ,比如list, ...

  4. Event事件、进程池与线程池、协程

    目录 Event事件 进程池与线程池 多线程爬取梨视频 协程 协程目的 gevent TCP服务端socket套接字实现协程 Event事件 用来控制线程的执行 出现e.wait(),就会把这个线程设 ...

  5. 《python》join、守护进程、锁/信号量/事件、进程队列

    一.multiprocess.process模块 1.join方法 阻塞主进程,等待子进程执行完毕再放开阻塞 import time import random from multiprocessin ...

  6. Python之进程 3 - 进程池和multiprocess.Poll

    一.为什么要有进程池? 在程序实际处理问题过程中,忙时会有成千上万的任务需要被执行,闲时可能只有零星任务.那么在成千上万个任务需要被执行的时候,我们就需要去创建成千上万个进程么?首先,创建进程需要消耗 ...

  7. 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)

    参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...

  8. python之路--管道, 事件, 信号量, 进程池

    一 . 管道 (了解) from multiprocessing import Process, Pipe def f1(conn): # 管道的recv 里面不用写数字 from_main_proc ...

  9. python 管道 事件(Event) 信号量 进程池(map/同步/异步)回调函数

    ####################总结######################## 管道:是进程间通信的第二种方式,但是不推荐使用,因为管道会导致数据不安全的情况出现 事件:当我运行主进程的 ...

随机推荐

  1. 分割窗口QSplitter类

    概述 分割窗口QSplitter类在应用程序中经常用到,它可以灵活分割窗口的布局,经常用在类似文件资源管理器的窗口设计中 在Qt开发中,QSplitter是比较常用到的,也就是分割窗口.并且窗口分割处 ...

  2. JAVA基础知识总结:十四

    一.泛型 1.概念 泛型指的是泛指的类型.主要用于子类和父类,接口和实现类之间的数据传递 JDK1.5之后新增的特性,主要用于解决安全问题,是一个安全机制 好处: a.可以提高代码的复用性 b.避免了 ...

  3. selenium+Page Objects(第三话)

    写好BasePage基类和页面元素定位后,就可以针对每个页面写业务逻辑了 1.编写每个页面page类,拿其中一个页面为例 fourth_page.py(名字我随便取的,实际中希望能取一些有意义的名字) ...

  4. Ubuntu终端多窗口分屏Terminator

    1.安装 Terminator最大的特点就是可以在一个窗口中打开多个终端 sudo apt-get install terminator 2.快捷键 Ctrl+Shift+E    垂直分割窗口 Ct ...

  5. ADO.NET连接池机制

    为什么需要连接池 剖析一个技术第一个要问的是,这项技术为什么存在. 对于每一个到SQL Server的连接,都需要经历TCP/IP协议的三次握手,身份认证,在SQL Server里建立连接,分配资源等 ...

  6. spring ----> 搭建spring+springmvc+mybatis出现的几个问题

    环境: idea ce 2018.1+maven3.5.3+mysql8.0.11+jdk1.8 spring4.3.7+spring mvc4.3.7+mybatis3.4.1+tomcat7.0. ...

  7. ubuntu opencv

    sudo apt-get updatesudo apt-get upgrade sudo apt-get install build-essential libgtk2.0-dev libjpeg-d ...

  8. IntelliJ IDEA 安装 Scala 插件

    本页面中对在 IntelliJ 中安装 Scala 插件的步骤和方法进行了描述. 需要在 IntelliJ  安装 Scala 插件,你首先需要在你的计算机中安装 IntelliJ .IntelliJ ...

  9. Count Up Down(上下计数)

    这个题目是 Kayak 发布的代码挑战题目. 最简单的描述就是不使用循环,输出 0 到 5,然后同样不是会用循环的方式再次输出 5 到 0. 英文描述 Part 1 Write a program t ...

  10. Tensor RT使用记录

    Tensor RT的介绍在此不做赘述. 自己在服务器上本打算装Tensor RT来着,不过过程很艰辛,最后发现服务器的cudnn版本偏低了,还需要升级cudnn的版本.故,在自己的电脑上了装了下Ten ...