day32 信号量 事件 管道 进程池

时间:2022-09-06 10:15:04

今日主要内容:

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. day31 管道 进程池 数据共享

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. python之管道, 事件, 信号量, 进程池

    管道:双向通信 2个进程之间相互通信 from multiprocessing import Process, Pipe def f1(conn): from_zjc_msg = conn.recv( ...

随机推荐

  1. Queue、进程、线程、协程

    参考博客地址 http://www.cnblogs.com/alex3714/articles/5230609.html 1.python GIL全局解释器锁 python调用的操作系统的原生线程,当 ...

  2. Winform禁止容器内控件获得焦点时改变容器显示范围坐标

    在Winform中当容器的可视高度无法显示所有控件并且容器的AutoScroll属性设置为True的情况下,但点击容器内某个未显示完整的控件时,会出现容器的滚动条自动下滚的情况. 这是由于控件获得焦点 ...

  3. android startActivityForResult的用法

    有时候我们需要把A activity提交数据给B  activity处理,然后把结果返回给A 这种方式在很多种情况需要用到,比如我应用的程序需要有拍照上传的功能. 一种解决方案是  我的应用程序 〉调 ...

  4. 【转】git使用教程

    Git使用教程 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在*服务器的,而干活的时候,用的都是 ...

  5. C语言原码反码补码与位运算.

      目录:     一.机器数和真值     二.原码,反码和补码的基础概念     三.为什么要使用原码,反码和补码     四.原码,补码,反码再深入     五.数据溢出测试     六.位运算 ...

  6. AltiumDesigner14板框定义及3D显示图文教程

    很多人都跟我反应说AD14不能定义板框大小,或者说是不知道怎么定义板框的大小,确实AD14的操作和AD13或者是AD10的版本斗有一些差异,尤其是现在最新的版本AltiumDesigner14.3.1 ...

  7. NSString、NSData、char* 类型之间的转换-备

    1. NSString转化为UNICODE String: (NSString*)fname = @“Test”; char fnameStr[10]; memcpy(fnameStr, [fname ...

  8. Xhprof graphviz Warning: proc_open() [function.proc-open]: CreateProcess failed, error code 解决方法

    Xhprof在windows下点击[View Full Callgraph]调用graphviz软件时.警告Warning: proc_open() [function.proc-open]: Cre ...

  9. Python 学习 第十六篇:networkx

    networkx是Python的一个包,用于构建和操作复杂的图结构,提供分析图的算法.图是由顶点.边和可选的属性构成的数据结构,顶点表示数据,边是由两个顶点唯一确定的,表示两个顶点之间的关系.顶点和边 ...

  10. 转载 基于JAVA每月运势api调用代码实例

    代码描述:基于JAVA每月运势api调用代码实例 接口地址:http://www.juhe.cn/docs/api/id/58 原文链接:http://outofmemory.cn/code-snip ...