在 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项目发布为exe可执行程序过程分享
Oct 23 Python
详解Python3.1版本带来的核心变化
Apr 07 Python
python实现图片处理和特征提取详解
Nov 13 Python
Python os.rename() 重命名目录和文件的示例
Oct 25 Python
python通过tcp发送xml报文的方法
Dec 28 Python
深入解析Python小白学习【操作列表】
Mar 23 Python
Django网络框架之创建虚拟开发环境操作示例
Jun 06 Python
Python csv模块使用方法代码实例
Aug 29 Python
如何Tkinter模块编写Python图形界面
Oct 14 Python
python使用selenium爬虫知乎的方法示例
Oct 28 Python
用Python的绘图库(matplotlib)绘制小波能量谱
Apr 17 Python
Django cookie和session的应用场景及如何使用
Apr 29 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
使用session判断用户登录用户权限(超简单)
2013/06/08 PHP
PHP利用func_get_args和func_num_args函数实现函数重载实例
2014/11/12 PHP
PHP获取服务器端信息的方法
2014/11/28 PHP
ThinkPHP整合datatables实现服务端分页的示例代码
2018/02/10 PHP
网页里控制图片大小的相关代码
2006/06/13 Javascript
javascript数字格式化通用类 accounting.js使用
2012/08/24 Javascript
extjs 04_grid 单击事件新发现
2012/11/27 Javascript
Extjs改变树节点的勾选状态点击按钮将复选框去掉
2013/11/14 Javascript
window.location不跳转的问题解决方法
2014/04/17 Javascript
angularjs实现的前端分页控件示例
2017/02/10 Javascript
详解使用angularjs的ng-options时如何设置默认值(初始值)
2017/07/18 Javascript
一个Js文件函数中调用另一个Js文件函数的方法演示
2017/08/14 Javascript
Node.js连接Sql Server 2008及数据层封装详解
2018/08/27 Javascript
浅谈Vue CLI 3结合Lerna进行UI框架设计
2019/04/14 Javascript
解决vue项目中遇到 Cannot find module ‘chalk‘ 报错的问题
2020/11/05 Javascript
vue+echarts实现中国地图流动效果(步骤详解)
2021/01/27 Vue.js
[01:00] DOTA2英雄背景故事第五期之重力引力法则谜团
2020/07/16 DOTA
为Python程序添加图形化界面的教程
2015/04/29 Python
详解Python的Django框架中的templates设置
2015/05/11 Python
Python爬虫爬取美剧网站的实现代码
2016/09/03 Python
python爬虫入门教程--利用requests构建知乎API(三)
2017/05/25 Python
Python检查 云备份进程是否正常运行代码实例
2019/08/22 Python
Python shelve模块实现解析
2019/08/28 Python
Python如何实现的二分查找算法
2020/05/27 Python
Ticketmaster意大利:音乐会、节日、艺术和剧院的官方门票
2019/12/23 全球购物
俄罗斯游戏商店:Buka
2020/03/01 全球购物
PPP协议组成及简述协议协商的基本过程
2015/05/28 面试题
大学毕业生通用求职信
2013/09/28 职场文书
工厂会计员职责
2014/02/06 职场文书
社区道德讲堂实施方案
2014/03/21 职场文书
爱心捐款倡议书范文
2014/05/12 职场文书
初中作文评语
2014/12/25 职场文书
煤矿隐患排查制度
2015/08/05 职场文书
2015年小学师德师风建设工作总结
2015/10/23 职场文书
全新239军机修复记
2022/04/05 无线电
Vue ECharts实现机舱座位选择展示功能
2022/05/15 Vue.js