在 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实现的检测网站挂马程序
Nov 30 Python
Python的SQLAlchemy框架使用入门
Apr 29 Python
浅谈django开发者模式中的autoreload是如何实现的
Aug 18 Python
python中退出多层循环的方法
Nov 27 Python
对pandas中时间窗函数rolling的使用详解
Nov 28 Python
Pytorch evaluation每次运行结果不同的解决
Jan 02 Python
python中线程和进程有何区别
Jun 17 Python
python 爬取英雄联盟皮肤并下载的示例
Dec 04 Python
python中entry用法讲解
Dec 04 Python
SpringBoot首页设置解析(推荐)
Feb 11 Python
Python虚拟环境virtualenv是如何使用的
Jun 20 Python
Python利用zhdate模块实现农历日期处理
Mar 31 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+AJAX传送中文会导致乱码的问题的解决方法
2008/09/08 PHP
php循环table实现一行两列显示的方法
2015/06/04 PHP
php生成mysql的数据字典
2016/07/07 PHP
php使用parse_str实现查询字符串解析到变量中的方法
2017/02/17 PHP
Laravel框架Eloquent ORM删除数据操作示例
2019/12/03 PHP
javaScript 判断字符串是否为数字的简单方法
2009/07/25 Javascript
判断iframe是否加载完成的完美方法
2010/01/07 Javascript
JQuery团队打造的javascript单元测试工具QUnit介绍
2010/02/26 Javascript
document.documentElement和document.body区别介绍
2013/09/16 Javascript
javascript获取选中的文本的方法代码
2013/10/30 Javascript
javascript中的Base64、UTF8编码与解码详解
2015/03/18 Javascript
10个很棒的jQuery代码片段
2015/09/24 Javascript
vue.js初学入门教程(1)
2016/11/03 Javascript
详解vuejs之v-for列表渲染
2017/06/22 Javascript
thinkjs 文件上传功能实例代码
2017/11/08 Javascript
vue 使用Jade模板写html,stylus写css的方法
2018/02/23 Javascript
vue-content-loader内容加载器的使用方法
2018/08/05 Javascript
js实现文件上传功能 后台使用MultipartFile
2018/09/08 Javascript
JavaScript继承的特性与实践应用深入详解
2018/12/30 Javascript
其实你可以少写点if else与switch(推荐)
2019/01/10 Javascript
在layui中select更改后生效的方法
2019/09/05 Javascript
vue iview的菜单组件Mune 点击不高亮的解决方案
2019/11/01 Javascript
JS 获取文件后缀,判断文件类型(比如是否为图片格式)
2020/05/09 Javascript
Python中的列表生成式与生成器学习教程
2016/03/13 Python
Python实现查找数组中任意第k大的数字算法示例
2019/01/23 Python
Numpy与Pytorch 矩阵操作方式
2019/12/27 Python
python+requests实现接口测试的完整步骤
2020/10/27 Python
德国骆驼商店:ActiveFashionWorld
2017/11/18 全球购物
函授大学生自我鉴定
2014/02/05 职场文书
民事诉讼授权委托书范文
2014/08/02 职场文书
2014年向国旗敬礼活动总结
2014/09/27 职场文书
代收款委托书范本
2014/10/01 职场文书
在职人员跳槽求职信
2015/03/20 职场文书
全国助残日活动总结
2015/05/11 职场文书
电影建国大业观后感
2015/06/01 职场文书
Python-OpenCV实现图像缺陷检测的实例
2021/06/11 Python