在 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 相关文章推荐
使用wxPython获取系统剪贴板中的数据的教程
May 06 Python
python操作mongodb根据_id查询数据的实现方法
May 20 Python
python GUI实例学习
Nov 21 Python
微信跳一跳游戏python脚本
Apr 01 Python
对matplotlib改变colorbar位置和方向的方法详解
Dec 13 Python
用Python编写一个高效的端口扫描器的方法
Dec 20 Python
Python设计模式之策略模式实例详解
Jan 21 Python
Python绘制频率分布直方图的示例
Jul 08 Python
scrapy爬虫:scrapy.FormRequest中formdata参数详解
Apr 30 Python
Python 整行读取文本方法并去掉readlines换行\n操作
Sep 03 Python
python tkinter的消息框模块(messagebox,simpledialog)
Nov 07 Python
Python实现列表索引批量删除的5种方法
Nov 16 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 HTML代码串截取代码
2008/12/29 PHP
解析crontab php自动运行的方法
2013/06/24 PHP
php遍历目录与文件夹的多种方法详解
2013/11/14 PHP
PHP实现文件下载断点续传详解
2014/10/15 PHP
PHP代码判断设备是手机还是平板电脑(两种方法)
2015/10/19 PHP
WordPress主题制作中自定义头部的相关PHP函数解析
2016/01/08 PHP
PHP实现的抓取小说网站内容功能示例
2019/06/27 PHP
javascript客户端解决方案 缓存提供程序
2010/07/14 Javascript
深入理解JavaScript系列(8) S.O.L.I.D五大原则之里氏替换原则LSP
2012/01/15 Javascript
jQuery实现随意改变div任意属性的名称和值(部分原生js实现)
2013/05/28 Javascript
纯js实现遮罩层效果原理分析
2014/05/27 Javascript
js实现div闪烁原理及实现代码
2014/06/24 Javascript
javascript比较两个日期相差天数的方法
2015/07/23 Javascript
JavaScript学习总结之JS、AJAX应用
2016/01/29 Javascript
jQuery实现的tab标签切换效果示例
2016/09/05 Javascript
JS中作用域和变量提升(hoisting)的深入理解
2016/10/31 Javascript
让你彻底掌握es6 Promise的八段代码
2017/07/26 Javascript
JS实现百度搜索框关键字推荐
2020/02/17 Javascript
OpenLayers加载缩放控件使用方法详解
2020/09/25 Javascript
[01:24]2014DOTA2 TI第二日 YYF表示这届谁赢都有可能
2014/07/11 DOTA
Python中的rfind()方法使用详解
2015/05/19 Python
如何在sae中设置django,让sae的工作环境跟本地python环境一致
2017/11/21 Python
python单线程文件传输的实例(C/S)
2019/02/13 Python
python利用selenium进行浏览器爬虫
2019/04/25 Python
Python学习笔记之Break和Continue用法分析
2019/08/14 Python
浅谈cv2.imread()和keras.preprocessing中的image.load_img()区别
2020/06/12 Python
python爬虫爬取某网站视频的示例代码
2021/02/20 Python
将世界上最美丽的摄影作品转化为艺术作品:Photos.com
2017/11/28 全球购物
技术学校毕业生求职信分享
2013/12/02 职场文书
工作迟到检讨书
2014/02/21 职场文书
机械电子工程专业求职信
2014/06/22 职场文书
国际贸易毕业生求职信
2014/07/20 职场文书
党的群众路线批评与自我批评发言稿
2014/10/16 职场文书
文明单位创建材料
2014/12/24 职场文书
使用Djongo模块在Django中使用MongoDB数据库
2021/06/20 Python
GoFrame基于性能测试得知grpool使用场景
2022/06/21 Golang