在 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的Django框架中创建和使用模版
Jul 15 Python
Python实现简单的多任务mysql转xml的方法
Feb 08 Python
利用selenium 3.7和python3添加cookie模拟登陆的实现
Nov 20 Python
浅析Git版本控制器使用
Dec 10 Python
Python之reload流程实例代码解析
Jan 29 Python
Sanic框架异常处理与中间件操作实例分析
Jul 16 Python
朴素贝叶斯Python实例及解析
Nov 19 Python
python os.path.isfile 的使用误区详解
Nov 29 Python
Django 项目通过加载不同env文件来区分不同环境
Feb 17 Python
python图片验证码识别最新模块muggle_ocr的示例代码
Jul 03 Python
python使用scapy模块实现ping扫描的过程详解
Jan 21 Python
python缺失值填充方法示例代码
Dec 24 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
VSCode+PHPstudy配置PHP开发环境的步骤详解
2020/08/20 PHP
Z-Blog中用到的js代码
2007/03/15 Javascript
PNG背景在不同浏览器下的应用
2009/06/22 Javascript
javascript让setInteval里的函数参数中的this指向特定的对象
2010/01/31 Javascript
让ie6也支持websocket采用flash封装实现
2013/02/18 Javascript
js原生appendChild的bug解决心得分享
2013/07/01 Javascript
Jquery右下角抖动、浮动 实例代码(兼容ie6、FF)
2013/08/15 Javascript
jQuery 计算iframe 窗口大小的方法
2014/05/13 Javascript
一个简单的jQuery插件ajaxfileupload.js实现ajax上传文件例子
2014/06/26 Javascript
javascript中对变量类型的判断方法
2015/08/09 Javascript
jQuery插件EasyUI获取当前Tab中iframe窗体对象的方法
2016/08/05 Javascript
php简单数据库操作类的封装
2017/06/08 Javascript
微信小程序getPhoneNumber获取用户手机号
2017/09/29 Javascript
vue2 前端搜索实现示例
2018/02/26 Javascript
JavaScript实现区块链
2018/03/14 Javascript
基于vue实现滚动条滚动到指定位置对应位置数字进行tween特效
2019/04/18 Javascript
通过javascript实现段落的收缩与展开
2019/06/26 Javascript
js String.prototype.trim字符去前后空格的扩展
2020/08/23 Javascript
原生jQuery实现只显示年份下拉框
2020/12/24 jQuery
Python实现多线程抓取网页功能实例详解
2017/06/08 Python
python处理csv数据动态显示曲线实例代码
2018/01/23 Python
python 实现在Excel末尾增加新行
2018/05/02 Python
Python切片操作去除字符串首尾的空格
2019/04/22 Python
Python的Lambda函数用法详解
2019/09/03 Python
给ubuntu18安装python3.7的详细教程
2020/06/08 Python
移动端解决悬浮层(悬浮header、footer)会遮挡住内容的3种方法
2015/03/27 HTML / CSS
西班牙家用电器和电子产品购物网站:Mi Electro
2019/02/25 全球购物
日本乐天德国站:Rakuten.de
2019/05/16 全球购物
优纳科技软件测试面试题
2012/05/15 面试题
2014三八妇女节活动总结范文四篇
2014/03/09 职场文书
三方协议书范本
2014/04/22 职场文书
我的中国梦演讲稿高中篇
2014/08/19 职场文书
运动会演讲稿200字
2014/08/25 职场文书
党性心得体会
2014/09/03 职场文书
2014年高中班主任工作总结
2014/11/08 职场文书
用Python写一个简易版弹球游戏
2021/04/13 Python