在 Python 中利用 Pool 进行多线程


Posted in Python onApril 24, 2022

为什么要引入线程池

如果在程序中经常要用到线程,频繁的创建和销毁线程会浪费很多硬件资源,
所以需要把线程和任务分离。线程可以反复利用,省去了重复创建的麻烦。
在 Process 类中,我们必须显式地创建流程。但是,Pool 类更方便,您不必手动管理它。创建池对象的语法是 ​​multiprocessing.Pool(processes, initializer, initargs, maxtasksperchild, context)​​ 。所有参数都是可选的。

  • processes 表示您要创建的工作进程的数量。默认值通过 os.cpu_count() 获取。
  • initializer第二个初始化器参数是一个用于初始化的函数。
  • initargs 是传递给它的参数。
  • maxtasksperchild 表示分配给每个子进程的任务数。在完成该数量的任务之后,该进程将被一个新的工作进程替换。指定它的好处是任何未使用的资源都将被释放。如果未提供任何内容,则只要池存在,进程就会存在。
import time
from multiprocessing import Pool


def square(x):
print(f"start process:{x}")
square = x * x
print(f"square {x}:{square}")
time.sleep(1)
print(f"end process:{x}")


if __name__ == "__main__":
starttime = time.time()
pool = Pool()
pool.map(square, range(0, 5))
pool.close()
endtime = time.time()
print(f"Time taken {endtime-starttime} seconds")

结果为:

start process:0
start process:1
square 1:1
square 0:0
end process:1
start process:2
end process:0
start process:3
square 2:4
square 3:9
end process:3
end process:2
start process:4
square 4:16
end process:4
Time taken 3.0474610328674316 seconds

在这里,我们从多处理模块中导入 Pool 类。在主函数中,我们创建了一个 Pool 类的对象。 pool.map() 将我们想要并行化的函数和一个可迭代的函数作为参数。它在可迭代的每个项目上运行给定的函数。它还接受一个可选的 chunksize 参数,它将可迭代对象拆分为等于给定大小的块,并将每个块作为单独的任务传递。 pool.close() 用于拒绝新任务。
我们可以看到花费的时间大约是 3 秒。
​pool.imap()​​ 与 ​​pool.map()​​ 方法几乎相同。不同的是,每个项目的结果都是在准备好后立即收到的,而不是等待所有项目都完成。此外, ​​map()​​ 方法将可迭代对象转换为列表(如果不是)。但是, ​​imap()​​ 方法没有。

来看下一个例子:

import time
from multiprocessing import Pool


def square(x):
print(f"start process {x}")
square = x * x
time.sleep(1)
print(f"end process {x}")
return square


if __name__ == "__main__":
pool = Pool()
a = pool.map(square, range(0, 5))
print(a)

运行结果:

start process 0
start process 1
end process 0
start process 2
end process 1
start process 3
end process 2
start process 4
end process 3
end process 4
[0, 1, 4, 9, 16]

from concurrent.futures import ThreadPoolExecutor

def say_hello():
print("Hello")

executor = ThreadPoolExecutor(50)
for i in range(0, 10):
executor.submit(say_hello)

练习

利用 Python 多线程模拟商品秒杀过程,不可以出现超买和超卖的情况。假设A商品有50件参与秒杀活动,10分钟秒杀自动结束。

  • kill_total 商品总数
  • kill_num 成功抢购数
  • kill_flag 有效标志位
  • kill_user 成功抢购的用户ID
from redis_db import pool
import redis
import random
from concurrent.futures import ThreadPoolExecutor

s = set()
while True:
if len(s) == 1000:
break
num = random.randint(10000, 100000)
s.add(num)
print(s)

con = redis.Redis(
connection_pool=pool
)

try:
con.delete("kill_total", "kill_num", "kill_flag", "kill_user")
con.set("kill_total", 50)
con.set("kill_num", 0)
con.set("kill_flag", 1)
con.expire("kill_flag", 600)

except Exception as e:
print(e)
finally:
del con

executor = ThreadPoolExecutor(200)
def buy():
connection = redis.Redis(
connection_pool=pool
)
pipline = connection.pipline()
try:
if connection.exists("kill_flag") == 1:
pipline.watch("kill_num", "kill_user")
total = pipline.get("kill_total")
num = int(pipline.get("kill_num").decode("utf-8"))
if num < total:
pipline.multi()
pipline.incr("kill_num")
user_id = s.pop()
pipline.rpush("kill_user", user_id)

pipline.execute()
except Exception as e:
print(e)
finally:
if "pipline" in dir():
pipline.reset()
del connection

for i in range(0, 1000):
executor.submit(buy)
print("秒杀活动已经结束")

到此这篇关于在 Python 中利用Pool 进行多处理的文章就介绍到这了!


Tags in this post...

Python 相关文章推荐
python实现的解析crontab配置文件代码
Jun 30 Python
使用Python对IP进行转换的一些操作技巧小结
Nov 09 Python
基于Python 的进程管理工具supervisor使用指南
Sep 18 Python
python利用正则表达式提取字符串
Dec 08 Python
利用pyinstaller或virtualenv将python程序打包详解
Mar 22 Python
Python闭包函数定义与用法分析
Jul 20 Python
python批量将excel内容进行翻译写入功能
Oct 10 Python
wxPython实现分隔窗口
Nov 19 Python
提升python处理速度原理及方法实例
Dec 25 Python
TensorFlow实现checkpoint文件转换为pb文件
Feb 10 Python
利用Python将图片中扭曲矩形的复原
Sep 07 Python
Python 远程开关机的方法
Nov 18 Python
Python何绘制带有背景色块的折线图
python中Pyqt5使用Qlabel标签播放视频
Apr 22 #Python
Python使用MapReduce进行简单的销售统计
python使用pycharm安装pyqt5以及相关配置
Python使用DFA算法过滤内容敏感词
python游戏开发之pygame实现接球小游戏
Apr 22 #Python
python游戏开发Pygame框架
Apr 22 #Python
You might like
数组任意位置插入元素,删除特定元素的实例
2017/03/02 PHP
PHP 实现字符串翻转(包含中文汉字)的实现代码
2017/04/01 PHP
PHP chunk_split()函数讲解
2019/02/12 PHP
Yii 框架控制器创建使用及控制器响应操作示例
2019/10/14 PHP
javascript 变量作用域 代码分析
2009/06/26 Javascript
定时器(setTimeout/setInterval)调用带参函数失效解决方法
2013/03/26 Javascript
Angularjs 滚动加载更多数据
2016/03/17 Javascript
基于JQuery实现图片上传预览与删除操作
2016/05/24 Javascript
基于javascript实现按圆形排列DIV元素(一)
2016/12/02 Javascript
Vue.js第四天学习笔记(组件)
2016/12/02 Javascript
JavaScript实现三级联动效果
2017/07/15 Javascript
Vue.js上下滚动加载组件的实例代码
2017/07/17 Javascript
JavaScript实现点击出现图片并统计点击次数功能示例
2018/07/23 Javascript
JS打印彩色菱形的实例代码
2018/08/15 Javascript
Vue组件教程之Toast(Vue.extend 方式)详解
2019/01/27 Javascript
如何使用VuePress搭建一个类型element ui文档
2019/02/14 Javascript
JS highcharts实现动态曲线代码示例
2020/10/16 Javascript
[32:56]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第二场 12.11
2020/12/16 DOTA
python3.4用循环往mysql5.7中写数据并输出的实现方法
2017/06/20 Python
Python获取Redis所有Key以及内容的方法
2019/02/19 Python
python实现计数排序与桶排序实例代码
2019/03/28 Python
python3.6环境安装+pip环境配置教程图文详解
2019/06/20 Python
python中的&amp;&amp;及||的实现示例
2019/08/07 Python
python每天定时运行某程序代码
2019/08/16 Python
Django项目之Elasticsearch搜索引擎的实例
2019/08/21 Python
解决python 读取excel时 日期变成数字并加.0的问题
2019/10/08 Python
简单介绍一下pyinstaller打包以及安全性的实现
2020/06/02 Python
Python pandas对excel的操作实现示例
2020/07/21 Python
Python利用pip安装tar.gz格式的离线资源包
2020/09/14 Python
Scrapy基于scrapy_redis实现分布式爬虫部署的示例
2020/09/29 Python
初中政教处工作总结
2015/08/12 职场文书
教师节主题班会教案
2015/08/17 职场文书
利用Python+OpenCV三步去除水印
2021/05/28 Python
浅谈@Value和@Bean的执行顺序问题
2021/06/16 Java/Android
Go语言空白表示符_的实例用法
2021/07/04 Golang
Android Flutter实现图片滑动切换效果
2022/04/07 Java/Android