进程池的同步与异步用法Pool
进程池的同步,如下程序:
from multiprocessing import Pool
import time
import os def func(n):
print('start 进程 %s'%n, os.getpid())
time.sleep(1)
print('end 进程 %s'%n, os.getpid()) if __name__ == "__main__":
pool = Pool() # 如果进程池不加数字,默认值为往前CPU的数量一样
for i in range(10):
pool.apply(func, args=(i,))
查看结果:
start 进程 0 21896
end 进程 0 21896
start 进程 1 27040
end 进程 1 27040
start 进程 2 23408
end 进程 2 23408
start 进程 3 29704
end 进程 3 29704
start 进程 4 31384
end 进程 4 31384
start 进程 5 2140
end 进程 5 2140
start 进程 6 25780
end 进程 6 25780
start 进程 7 29488
end 进程 7 29488
start 进程 8 21896
end 进程 8 21896
start 进程 9 27040
end 进程 9 27040
可以发现,变成了进程变成了同步得了,运行特别慢。
apply方法的作用就是将进程池的进程变成同步的。
将进程池变成异步的,使用apply_async就可以了,如下:
from multiprocessing import Pool
import time
import os def func(n):
print('start 进程 %s'%n, os.getpid())
time.sleep(1)
print('end 进程 %s'%n, os.getpid()) if __name__ == "__main__":
pool = Pool()
for i in range(10):
pool.apply_async(func, args=(i,))
但是发现结果什么都没有,因为主进程没有等子进程的结束就执行完了。
如下优化,使用join就行了:
from multiprocessing import Pool
import time
import os def func(n):
print('start 进程 %s'%n, os.getpid())
time.sleep(1)
print('end 进程 %s'%n, os.getpid()) if __name__ == "__main__":
pool = Pool()
for i in range(10):
pool.apply_async(func, args=(i,))
pool.close() # close()保证的是没有新的任务进入进程池
pool.join() # 这里的join检测的是子进程里面的任务结束,而不是子进程的结束,因为进程池里面的进程不会结束,永远活着,被用完之后会被还到进程池里面。
看结果:
start 进程 0 22364
start 进程 1 25820
start 进程 2 27688
start 进程 3 26840
start 进程 4 31100
start 进程 5 27032
start 进程 6 21452
start 进程 7 25592
end 进程 0 22364
start 进程 8 22364
end 进程 1 25820
start 进程 9 25820
end 进程 2 27688
end 进程 3 26840
end 进程 4 31100
end 进程 5 27032
end 进程 6 21452
end 进程 7 25592
end 进程 8 22364
end 进程 9 25820
值得注意的是,不加pool.close(),直接加pool.join()是会报错的,因为进程池里面的进程用完之后不会结束,而是被还到进程池了,因此这里的join检测的是没有任务再进入进程池了,而不是检测子进程的结束。所以要保证没有任务进入进程池,进程池就不会接收到任务,所以pool.close()的作用就是结束进程池接收任务,就是我的任务执行完毕,且没有新的任务进来,这是就被join检测到了。
另一种问题如下:
from multiprocessing import Pool
import time def func(n):
time.sleep(0.5)
return n*n if __name__ == "__main__":
pool = Pool(5)
for i in range(10):
ret = pool.apply(func, args=(i,))
print(ret)
打印结果:
0
1
4
9
16
25
36
49
64
81 # 每隔0.5秒打印一个结果
看下一段代码,使用apply_async:
from multiprocessing import Pool
import time def func(n):
time.sleep(0.5)
return n*n if __name__ == "__main__":
pool = Pool(5)
for i in range(10):
ret = pool.apply_async(func, args=(i,))
print(ret)
看打印结果:
<multiprocessing.pool.ApplyResult object at 0x0000023993E70AC8>
<multiprocessing.pool.ApplyResult object at 0x0000023993E70B70>
<multiprocessing.pool.ApplyResult object at 0x0000023993E70CF8>
<multiprocessing.pool.ApplyResult object at 0x0000023993E70DA0>
<multiprocessing.pool.ApplyResult object at 0x0000023993E70E80>
<multiprocessing.pool.ApplyResult object at 0x0000023993E70F28>
<multiprocessing.pool.ApplyResult object at 0x0000023993E70FD0>
<multiprocessing.pool.ApplyResult object at 0x0000023993E810B8>
<multiprocessing.pool.ApplyResult object at 0x0000023993E81160>
<multiprocessing.pool.ApplyResult object at 0x0000023993E81208>
是一个个对象,并且是同时打印出来的。
优化如下,使用get()方法获取值:
from multiprocessing import Pool
import time def func(n):
time.sleep(0.5)
return n*n if __name__ == "__main__":
pool = Pool(5)
for i in range(10):
ret = pool.apply_async(func, args=(i,))
print(ret.get())
看打印结果:
0
1
4
9
16
25
36
49
64
81
值出来的,但是你会发现一个现象,值是每隔0.5秒一个一个出来的,不是异步吗???
这里要注意for循环将任务传入如进程池时,
for i in range(10):
ret = pool.apply_async(func, args=(i,)) # for循环传入任务
print(ret.get())
执行到print(ret.get()),这里的get需要获取值,但是这是没有值,get就会让程序出现阻塞直到等到值,所以for循环的每一步都要等到值才会继续下一个for循环,就出现了不是异步的情况。
改进方法:
from multiprocessing import Pool
import time def func(n):
time.sleep(0.5)
return n*n if __name__ == "__main__":
pool = Pool(5)
l_list = []
for i in range(10):
ret = pool.apply_async(func, args=(i,))
l_list.append(ret)
for m in l_list:
print(m.get())
这时候你会发现五个五个的出现。
结束!
进程池的同步与异步用法Pool的更多相关文章
- 进程(并发,并行) join start 进程池 (同步异步)
一.背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象.进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有 ...
- python 管道 事件(Event) 信号量 进程池(map/同步/异步)回调函数
####################总结######################## 管道:是进程间通信的第二种方式,但是不推荐使用,因为管道会导致数据不安全的情况出现 事件:当我运行主进程的 ...
- 4月27日 python学习总结 GIL、进程池、线程池、同步、异步、阻塞、非阻塞
一.GIL:全局解释器锁 1 .GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在解释器身上的, 同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码 2.GIL的优缺点: 优点: 保 ...
- spring线程池的同步和异步(1)
spring线程池(同步.异步) 一.spring异步线程池类图 二.简单介绍 2.1. TaskExecutor---Spring异步线程池的接口类,其实质是java.util.concurrent ...
- GIL全局解释器锁+GIL全局解释器锁vs互斥锁+定时器+线程queue+进程池与线程池(同步与异步)
以多线程为例写个互斥锁 from threading import Thread ,Lockimport timemutex = Lock() n = 100 def task(): global n ...
- day 32 管道,信号量,进程池,线程的创建
1.管道(了解) Pipe(): 在进程之间建立一条通道,并返回元组(conn1,conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须在产生Process对象之前产生管道. ...
- {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll
Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...
- CIL锁,GIL与线程池的区别,进程池和线程池,同步与异步
一.GIL锁 什么是GIL? 全局解释器锁,是加在解释器上的互斥锁 GC是python自带的内存管理机制,GC的工作原理:python中的内存管理使用的是应用计数,每个数会被加上一个整型的计数器,表示 ...
- GIL 线程池 进程池 同步 异步
1.GIL(理论 重点)2.线程池 进程池3.同步 异步 GIL 是一个全局解释器锁,是一个互斥锁 为了防止竞争解释器资源而产生的 为何需要gil:因为一个python.exe进程中只有一份解释器,如 ...
随机推荐
- HTML5 学习04—— MathML数学标记
MathML 元素标签: <math>...</math> MathML 是数学标记语言,是一种基于XML(标准通用标记语言的子集)的标准,用来在互联网上书写数学符号和公式的置 ...
- 国内的Android SDK镜像
如果你不愿意改hosts文件,没有好的FQ工具,可以考虑使用国内的镜像源 1.南阳理工学院镜像服务器地址: mirror.nyist.edu.cn 端口:80 2.中国科学院开源协会镜像站地址: IP ...
- mvn -N和-U的用法
mvn参数-N.-U理解 关于-N -N,--non-recursive Do not recurse into sub-projects 意思是,不递归到子项目(子模块). 举例: 一个父项目下Fa ...
- iOS:Gif动画功能(显示gif动画、获取gif动画时长、获取gif动画执行次数)
一.简单介绍 gif动画是iOS开发中很常用的一个功能,有的是为了显示加载视频的过程,更多的是为了显示一个结果状态(动画更直观). 那么如何执行gif动画,方法有很多.(这里只写一下方法三,前两种之前 ...
- StompJS使用文档总结
STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,简单(流)文本定向消息协议,它提供了一个可互操作的连接格式,允许STOMP ...
- iOS NSDictionary 转Json 去掉换行去掉空格
//dic 转json 如果用系统自带的会出现空格. + (NSString *)returnJSONStringWithDictionary:(NSDictionary *)dictionary{ ...
- docker 端口映射 及外部无法访问问题
docker容器内提供服务并监听8888端口,要使外部能够访问,需要做端口映射. docker run -it --rm -p : server:v1 此时出现问题,在虚机A上部署后,在A内能够访问8 ...
- manjaro折腾手记
以前装过Arch,有点折腾,写了个hello world就卸载了.没用过AUR,甚至也没去了解. 听说manjaro继承Arch,几乎开箱即用,对硬件支持非常好,源里面的软件更新非常快.但是没有装中文 ...
- keil软件错误总结.doc
KEIL编译错误信息表 错误代码及错误信息 错误释义 error 1: Out of memory 内存溢出 error 2: Identifier expected 缺标识符 error 3: ...
- 分析轮子(一)-ArrayList.java
前言:之前也看过一些JDK源码,不过没有留下痕迹,经久年月就淡忘了,现在的时机也差不多了,想再看一次,并且记录下来自己的感想,于是从自己使用最多最熟悉的地方开始!并且看的过程中,我希望自己思考一下如下 ...