进程池的同步,如下程序:

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的更多相关文章

  1. 进程(并发,并行) join start 进程池 (同步异步)

    一.背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象.进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有 ...

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

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

  3. 4月27日 python学习总结 GIL、进程池、线程池、同步、异步、阻塞、非阻塞

    一.GIL:全局解释器锁 1 .GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在解释器身上的, 同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码 2.GIL的优缺点: 优点:  保 ...

  4. spring线程池的同步和异步(1)

    spring线程池(同步.异步) 一.spring异步线程池类图 二.简单介绍 2.1. TaskExecutor---Spring异步线程池的接口类,其实质是java.util.concurrent ...

  5. GIL全局解释器锁+GIL全局解释器锁vs互斥锁+定时器+线程queue+进程池与线程池(同步与异步)

    以多线程为例写个互斥锁 from threading import Thread ,Lockimport timemutex = Lock() n = 100 def task(): global n ...

  6. day 32 管道,信号量,进程池,线程的创建

    1.管道(了解) Pipe(): 在进程之间建立一条通道,并返回元组(conn1,conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须在产生Process对象之前产生管道. ...

  7. {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll

    Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...

  8. CIL锁,GIL与线程池的区别,进程池和线程池,同步与异步

    一.GIL锁 什么是GIL? 全局解释器锁,是加在解释器上的互斥锁 GC是python自带的内存管理机制,GC的工作原理:python中的内存管理使用的是应用计数,每个数会被加上一个整型的计数器,表示 ...

  9. GIL 线程池 进程池 同步 异步

    1.GIL(理论 重点)2.线程池 进程池3.同步 异步 GIL 是一个全局解释器锁,是一个互斥锁 为了防止竞争解释器资源而产生的 为何需要gil:因为一个python.exe进程中只有一份解释器,如 ...

随机推荐

  1. 好书推荐计划:Keras之父作品《Python 深度学习》

    大家好,我禅师的助理兼人工智能排版住手助手条子.可能非常多人都不知道我.由于我真的难得露面一次,天天给禅师做底层工作. wx_fmt=jpeg" alt="640? wx_fmt= ...

  2. ld: framework not found FileProvider for architecture arm64

    出现这个问题是因为  静态库是用Xcode9打包的. 如果用xcode8编译的话就会出现这个问题 解决办法 从Xcode9里把这个库拷贝出来.然后放到Xcode8上面 One way to fix t ...

  3. $gopath not set的解决办法

    执行安装 sudo go get github.com/nsf/gocode 提示: cannot download, $GOPATH not set. For more details see: g ...

  4. 使用Træfɪk(traefik)来加速Qt在线更新

    简述 在使用Qt的MaintenanceTool程序进行在线更新的时候遇到一个问题,就是访问download.qt.io实在太慢了,老是失败.所以想使用国内的镜像站来进行更新. 使用Qt的镜像站方法也 ...

  5. 关于Docker目录挂载的总结(转)

    关于Docker目录挂载的总结 Docker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定. 譬如我要启动一个centos容器,宿主机的/test目录挂载到容器的/soft目录,可通过 ...

  6. java.lang.IllegalStateException: Cannot run without an instance id.

    启动springboot,报错:quartz集群报错: Sep 09, 2016 5:33:47 AM org.apache.catalina.core.ApplicationContext log ...

  7. python 奇偶拆分list,python拆分list,得到一个原来list的奇数list,一个原来list的偶数list

    需求:现在有一个list ,range_data = ['m', 'M', 'h', 'c', 'X', 'Z', 'A', 'o'] 希望得到两个list,  一个是奇数list =['m', 'h ...

  8. 论如何优雅的自定义ThreadPoolExecutor线程池

    更好的markDown阅读体验可直接访问我的CSDN博客:https://blog.csdn.net/u012881584/article/details/85221635 前言 线程池想必大家也都用 ...

  9. Django-jet自定义菜单

    Django-jet自定义菜单:并且可设置权限.https://jet.readthedocs.io/en/latest/config_file.html#custom-menu

  10. scrapy框架Selector提取数据

    从页面中提取数据的核心技术是HTTP文本解析,在python中常用的模块处理: BeautifulSoup  非常流行的解析库,API简单,但解析的速度慢. lxml 是一套使用c语言编写的xml解析 ...