Python中的进程池与线程池
引入进程池与线程池
使用ProcessPoolExecutor进程池,使用ThreadPoolExecutor
使用shutdown
使用submit同步调用
使用submit异步调用
异步+回调函数
并发实现套接字通信
引入进程池
在学习线程池之前,我们先看一个例子
# from multiprocessing import Process
# import time
#
# def task(name):
# print('name',name)
# time.sleep(1)
# if __name__ == '__main__':
# start=time.time()
# p1 = Process(target=task,args=("safly1",))
# p2 = Process(target=task, args=("safly2",))
# p3 = Process(target=task, args=("safly3",))
#
# p1.start()
# p2.start()
# p3.start()
#
# p1.join()
# p2.join()
# p3.join()
#
# print("main")
#
# end = time.time()
# print(end- start)
输出如下:

以上的方式是一个个创建进程,这样的耗费时间才1秒多,虽然高效,但是有什么弊端呢?
如果并发很大的话,会给服务器带来很大的压力,所以引入了进程池的概念
使用ProcessPoolExecutor进程池
什么时候用池:
池的功能是限制启动的进程数或线程数,
什么时候应该限制???
当并发的任务数远远超过了计算机的承受能力时,即无法一次性开启过多的进程数或线程数时
就应该用池的概念将开启的进程数或线程数限制在计算机可承受的范围内
Python3.2开始,标准库为我们提供了concurrent.futures模块,它提供了ThreadPoolExecutor和ProcessPoolExecutor两个类,实现了对threading和multiprocessing的进一步抽象,对编写线程池/进程池提供了直接的支持。
通过ProcessPoolExecutor 来做示例。
我们来看一个最简单的进程池
from concurrent.futures import ProcessPoolExecutor
import time
def task(name):
print('name',name)
time.sleep(1)
if __name__ == '__main__':
start=time.time()
p1=ProcessPoolExecutor(2)
for i in range(5):
p1.submit(task,i)
p1.shutdown(wait=True)
print('主')
end=time.time()
print(end-start)
输出如下:
D:\APPS\Python3.7\python.exe "D:/Python/project one/day20180717/进程池与线程池.py"
name 0
name 1
name 2
name 3
name 4
主
3.118098258972168 Process finished with exit code 0
简单解释下:
ProcessPoolExecutor(2)创建一个进程池,容量为2,循环submit出5个进程,然后就在线程池队列里面,执行多个进程,p1.shutdown(wait=True)意思是进程都执行完毕,在执行主进程的内容
使用shutdown
p1.shutdown(wait=True)是进程池内部的进程都执行完毕,才会关闭,然后执行后续代码
如果改成false呢?看如下代码
from concurrent.futures import ProcessPoolExecutor
import time
def task(name):
print('name',name)
time.sleep(1)
if __name__ == '__main__':
start=time.time()
p1=ProcessPoolExecutor(2)
for i in range(5):
p1.submit(task,i)
p1.shutdown(wait=False)
print('主')
end=time.time()
print(end-start)
输出如下:
D:\APPS\Python3.7\python.exe "D:/Python/project one/day20180717/进程池与线程池.py"
主
0.008975744247436523
name 0
name 1
name 2
name 3
name 4 Process finished with exit code 0
使用submit同步调用
同步:提交完任务后就在原地等待,直到任务运行完毕并且拿到返回值后,才运行下一行代码
from concurrent.futures import ProcessPoolExecutor
import time, random, os def piao(name, n):
print('%s is piaoing %s' % (name, os.getpid()))
time.sleep(1)
return n ** 2 if __name__ == '__main__':
p = ProcessPoolExecutor(2)
start = time.time()
for i in range(5):
res=p.submit(piao,'safly %s' %i,i).result() #同步调用
print(res) p.shutdown(wait=True)
print('主', os.getpid()) stop = time.time()
print(stop - start)
D:\APPS\Python3.7\python.exe "D:/Python/project one/day20180717/进程池与线程池.py"
safly 0 is piaoing 11448
0
safly 1 is piaoing 11800
1
safly 2 is piaoing 11448
4
safly 3 is piaoing 11800
9
safly 4 is piaoing 11448
16
主 8516
5.095325946807861 Process finished with exit code 0
使用submit异步调用
异步:提交完任务(绑定一个回调函数)后不原地等待,直接运行下一行代码,等到任务运行有返回值自动触发回调的函数的运行
from concurrent.futures import ThreadPoolExecutor
import time
def task(name):
print('name',name)
time.sleep(1)
if __name__ == '__main__':
start=time.time()
p1=ThreadPoolExecutor(2)
for i in range(5):
p1.submit(task,i)
p1.shutdown(wait=True)
print('主')
end=time.time()
print(end-start)
简单小例子
D:\APPS\Python3.7\python.exe "D:/Python/project one/day20180717/进程池与线程池.py"
name 0
name 1
name 2
name 3
name 4
主
3.003053903579712
结果
使用回调函数+异步
# from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
# import os
# import time
# import random
#
# def task(n):
# print('%s run...' %os.getpid())
# time.sleep(5)
# return n**2
#
# def parse(future):
# time.sleep(1)
# res=future.result()
# print('%s 处理了 %s' %(os.getpid(),res))
#
# if __name__ == '__main__':
# pool=ProcessPoolExecutor(4)
# # pool.submit(task,1)
# # pool.submit(task,2)
# # pool.submit(task,3)
# # pool.submit(task,4)
#
# start=time.time()
# for i in range(1,5):
# future=pool.submit(task,i)
# future.add_done_callback(parse) # parse会在futrue有返回值时立刻触发,并且将future当作参数传给parse
# pool.shutdown(wait=True)
# stop=time.time()
# print('主',os.getpid(),(stop - start))
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import current_thread
import os
import time
import random def task(n):
print('%s run...' %current_thread().name)
time.sleep(5)
return n**2 def parse(future):
time.sleep(1)
res=future.result()
print('%s 处理了 %s' %(current_thread().name,res)) if __name__ == '__main__':
pool=ThreadPoolExecutor(4)
start=time.time()
for i in range(1,5):
future=pool.submit(task,i)
future.add_done_callback(parse) # parse会在futrue有返回值时立刻触发,并且将future当作参数传给parse
pool.shutdown(wait=True)
stop=time.time()
print('主',current_thread().name,(stop - start))
线程
并发实现套接字通信
from socket import *
from threading import Thread def talk(conn):
while True:
try:
data=conn.recv(1024)
if len(data) == 0:break
conn.send(data.upper())
except ConnectionResetError:
break
conn.close() def server(ip,port,backlog=5):
server = socket(AF_INET, SOCK_STREAM)
server.bind((ip, port))
server.listen(backlog) print('starting...')
while True:
conn, addr = server.accept() t = Thread(target=talk, args=(conn,))
t.start() if __name__ == '__main__':
server('127.0.0.1',8080)
服务端
from socket import *
import os client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080)) while True:
msg='%s say hello' %os.getpid()
client.send(msg.encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8'))
客户端
扩展:
回调函数(callback)是什么?
以下均来自知乎:

回调函数(callback)是什么? - no.body的回答 - 知乎 https://www.zhihu.com/question/19801131/answer/27459821
非常经典的回答加举例。
Python中的进程池与线程池的更多相关文章
- Python中的进程池与线程池(包含代码)
Python中的进程池与线程池 引入进程池与线程池 使用ProcessPoolExecutor进程池,使用ThreadPoolExecutor 使用shutdown 使用submit同步调用 使用su ...
- python中的进程池
1.进程池的概念 python中,进程池内部会维护一个进程序列.当需要时,程序会去进程池中获取一个进程. 如果进程池序列中没有可供使用的进程,那么程序就会等待,直到进程池中有可用进程为止. 2.进程池 ...
- python系列之 - 并发编程(进程池,线程池,协程)
需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...
- python并发编程之进程池,线程池,协程
需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...
- python并发编程之进程池,线程池concurrent.futures
进程池与线程池 在刚开始学多进程或多线程时,我们迫不及待地基于多进程或多线程实现并发的套接字通信,然而这种实现方式的致命缺陷是:服务的开启的进程数或线程数都会随着并发的客户端数目地增多而增多, 这会对 ...
- Python并发编程之进程池与线程池
一.进程池与线程池 python标准模块concurrent.futures(并发未来) 1.concurrent.futures模块是用来创建并行的任务,提供了更高级别的接口,为了异步执行调用 2. ...
- python 36 进程池、线程池
目录 1. 死锁与递归锁 2. 信号量Semaphor 3. GIL全局解释器锁:(Cpython) 4. IO.计算密集型对比 4.1 计算密集型: 4.2 IO密集型 5. GIL与Lock锁的区 ...
- python并发编程之进程池、线程池、协程
需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...
- GIL全局解释器锁、死锁现象、python多线程的用处、进程池与线程池理论
昨日内容回顾 僵尸进程与孤儿进程 # 僵尸进程: 所有的进程在运行结束之后并不会立刻销毁(父进程需要获取该进程的资源) # 孤儿进程: 子进程正常运行 但是产生该子进程的父进程意外死亡 # 守护进程: ...
随机推荐
- C语言复制数组
直接上代码,分别是栈上开辟内存,堆上开辟内存 #include <stdio.h> #include <stdlib.h> void test01(){ ]; printf(& ...
- hibernate4一对多关联多方多写一次外键导致无法创建java.lang.NullPointerException以及Cannot add or update a child row: a foreign key constraint fails
一篇文章里边有多张图片,典型的单向一对多关系 多方 当程序运行到这一句的时候必然报错 但是参考书也是这样写的 其中em是 EntityManager em = JPA.createEntityMana ...
- 修改maven本地库路径
1.打开maven的安装路径:${M2_HOME}/conf/setings.xml文件 2.找到<localRepository>项,将它的值修改就可以了,我修改的是:${M2_HOME ...
- 利用TensorFlow识别手写的数字---基于Softmax回归
1 MNIST数据集 MNIST数据集主要由一些手写数字的图片和相应的标签组成,图片一共有10类,分别对应从0-9,共10个阿拉伯数字.原始的MNIST数据库一共包含下面4个文件,见下表. 训练图像一 ...
- videojs使用的常见问题
1.报错The play() request was interrupted by a new load request 我在动态更换video的url时会报这个错.修改一下原来的代码如下,就正常了 ...
- [Array]283. Move Zeroes
Given an array nums, write a function to move all 0's to the end of it while maintaining the relativ ...
- [转]Event loop——浏览器和Node区别
最近对Event loop比较感兴趣,所以了解了一下.但是发现整个Event loop尽管有很多篇文章,但是没有一篇可以看完就对它所有内容都了解的文章.大部分的文章都只阐述了浏览器或者Node二者之一 ...
- CodeChef August Lunchtime 2014 题解
A题 给一个由a和b两种类型的字符组成的字符串,每次可以从中选取任意长度的回文子序列(不一定连续)并删除.问最少需要几次能将整个字符串为空. 思路:如果本身是个回文串,那么只需要一次,否则需要两次(第 ...
- 为什么打不开IDEA或webStorm官方网页?
为什么打不开IDEA或webStorm官方网页? 一.问题描述 idea和webStorm的官网:https://www.jetbrains.com/ 有时候打开idea的官网会出现无法访问的情况,页 ...
- leetcode 76 dp& 强连通分量&并查集经典操作
800. Similar RGB Color class Solution { int getn(int k){ return (k+8)/17; } string strd(int k){ char ...