在 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实现的最近最少使用算法
Jul 10 Python
python去除扩展名的实例讲解
Apr 23 Python
对python sklearn one-hot编码详解
Jul 10 Python
pycharm编写spark程序,导入pyspark包的3中实现方法
Aug 02 Python
python实现BP神经网络回归预测模型
Aug 09 Python
python+OpenCV实现车牌号码识别
Nov 08 Python
基于MSELoss()与CrossEntropyLoss()的区别详解
Jan 02 Python
Python正则表达式高级使用方法汇总
Jun 18 Python
Python实现敏感词过滤的4种方法
Sep 12 Python
python线程池 ThreadPoolExecutor 的用法示例
Oct 10 Python
一个非常简单好用的Python图形界面库(PysimpleGUI)
Dec 28 Python
Python 解决空列表.append() 输出为None的问题
May 23 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
PHP+redis实现的购物车单例类示例
2019/02/02 PHP
php中isset与empty函数的困惑与用法分析
2019/07/05 PHP
asp.net和php的区别点总结
2019/10/10 PHP
js 数值项目的格式化函数代码
2010/05/14 Javascript
基于JQuery 的消息提示框效果代码
2011/07/31 Javascript
ExtJS4中的requires使用方法示例介绍
2013/12/03 Javascript
javascript操作excel生成报表全攻略
2014/05/04 Javascript
Javascript学习笔记之 对象篇(三) : hasOwnProperty
2014/06/24 Javascript
EasyUI闪屏EasyUI页面加载提示(原理+代码+效果图)
2016/02/21 Javascript
浅析JavaScript中浏览器的兼容问题
2016/04/19 Javascript
AngularJS监听路由变化的方法
2017/03/07 Javascript
vue 中自定义指令改变data中的值
2017/06/02 Javascript
React-Native 组件之 Modal的使用详解
2017/08/08 Javascript
jquery实现点击a链接,跳转之后,该a链接处显示背景色的方法
2018/01/18 jQuery
解决vue-router中的query动态传参问题
2018/03/20 Javascript
webpack4打包vue前端多页面项目
2018/09/17 Javascript
使用javascript做时间倒数读秒功能的实例
2019/01/23 Javascript
微信小程序开发常见问题及解决方案
2019/07/11 Javascript
Python环境下安装使用异步任务队列包Celery的基础教程
2016/05/07 Python
Python图像处理之图像的缩放、旋转与翻转实现方法示例
2019/01/04 Python
pandas.read_csv参数详解(小结)
2019/06/21 Python
python 计算数据偏差和峰度的方法
2019/06/29 Python
python3 批量获取对应端口服务的实例
2019/07/25 Python
python django生成迁移文件的实例
2019/08/31 Python
关于Django Models CharField 参数说明
2020/03/31 Python
python利用platform模块获取系统信息
2020/10/09 Python
欧洲著名的珠宝和手表网上商城:uhrcenter
2017/04/10 全球购物
德国汽车零件和汽车配件网上商店:kfzteile24
2018/11/14 全球购物
小加工厂管理制度
2014/01/21 职场文书
留学推荐信怎么写
2014/01/25 职场文书
人力管理专业毕业生求职信
2014/02/27 职场文书
群众路线查摆问题及整改措施
2014/10/10 职场文书
万能检讨书
2015/01/27 职场文书
公司环境卫生管理制度
2015/08/05 职场文书
小学五年级班主任工作经验交流材料
2015/11/02 职场文书
如何开发一个渐进式Web应用程序PWA
2021/05/10 Javascript