在 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实现查询苹果手机维修进度
Mar 16 Python
Python执行时间的计算方法小结
Mar 17 Python
python 简单的绘图工具turtle使用详解
Jun 21 Python
python 环境变量和import模块导入方法(详解)
Jul 11 Python
详解使用 pyenv 管理多个版本 python 环境
Oct 19 Python
python中的字典操作及字典函数
Jan 03 Python
Python实现字符串匹配的KMP算法
Apr 04 Python
django-初始配置(纯手写)详解
Jul 30 Python
python django model联合主键的例子
Aug 06 Python
对django的User模型和四种扩展/重写方法小结
Aug 17 Python
利用keras加载训练好的.H5文件,并实现预测图片
Jan 24 Python
Python切片列表字符串如何实现切换
Aug 06 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
推荐几款用 Sublime Text 开发 Laravel 所用到的插件
2014/10/30 PHP
既简单又安全的PHP验证码 附调用方法
2016/06/02 PHP
Laravel5框架添加自定义辅助函数的方法
2018/08/01 PHP
JavaScript 对象链式操作测试代码
2010/04/25 Javascript
jQuery实现的立体文字渐变效果
2010/05/17 Javascript
jQuery 属性选择器element[herf*='value']使用示例
2013/10/20 Javascript
JQuery表单验证插件EasyValidator用法分析
2014/11/15 Javascript
使用js画图之画切线
2015/01/12 Javascript
JavaScript常用脚本汇总(三)
2015/03/04 Javascript
uploader秒传图片到服务器完整代码
2017/04/22 Javascript
BootStrap表单控件之文本域textarea
2017/05/23 Javascript
浅谈vue2 单页面如何设置网页title
2017/11/08 Javascript
详解.vue文件解析的实现
2018/06/11 Javascript
解决vue2 在mounted函数无法获取prop中的变量问题
2018/11/15 Javascript
mpvue实现小程序签到金币掉落动画(api实现)
2019/10/17 Javascript
解决vue.js中settimeout遇到的问题(时间参数短效果不稳定)
2020/07/21 Javascript
javascript如何使用函数random来实现课堂随机点名方法详解
2020/07/28 Javascript
Angular短信模板校验代码
2020/09/23 Javascript
JavaScript canvas实现跟随鼠标移动小球
2021/02/09 Javascript
[28:07]完美世界DOTA2联赛PWL S3 Phoenix vs INK ICE 第二场 12.13
2020/12/17 DOTA
通过Pandas读取大文件的实例
2018/06/07 Python
Flask框架 CSRF 保护实现方法详解
2019/10/30 Python
分享PyCharm的几个使用技巧
2019/11/10 Python
Python bytes string相互转换过程解析
2020/03/05 Python
彪马香港官方网上商店:PUMA香港
2020/12/06 全球购物
上海某公司.net方向笔试题
2014/09/14 面试题
班组长岗位职责范本
2014/01/05 职场文书
三年级班级文化建设方案
2014/05/04 职场文书
公益广告标语
2014/06/19 职场文书
教师批评与自我批评总结
2014/10/16 职场文书
保护校园环境倡议书
2015/04/28 职场文书
个人道歉信大全
2019/04/11 职场文书
MySQL库表名大小写的选择
2021/06/05 MySQL
Python中基础数据类型 set集合知识点总结
2021/08/02 Python
Vue监视数据的原理详解
2022/02/24 Vue.js
Java中Quartz高可用定时任务快速入门
2022/04/03 Java/Android