在 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中使用PIL模块处理图像的教程
Apr 29 Python
centos 安装python3.6环境并配置虚拟环境的详细教程
Feb 22 Python
Python paramiko模块的使用示例
Apr 11 Python
Python读取数据集并消除数据中的空行方法
Jul 12 Python
python 字典修改键(key)的几种方法
Aug 10 Python
如何用C代码给Python写扩展库(Cython)
May 17 Python
python 实现提取log文件中的关键句子,并进行统计分析
Dec 24 Python
python中文分词库jieba使用方法详解
Feb 11 Python
Python单例模式的四种创建方式实例解析
Mar 04 Python
Python reversed函数及使用方法解析
Mar 17 Python
解决python中import文件夹下面py文件报错问题
Jun 01 Python
新手必备Python开发环境搭建教程
May 28 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
1 Tube Radio
2021/03/02 无线电
PHP安全防范技巧分享
2011/11/03 PHP
php下载文件源代码(强制任意文件格式下载)
2014/05/09 PHP
PHP Web表单生成器案例分析
2020/06/02 PHP
理解JavaScript的caller,callee,call,apply
2009/04/28 Javascript
js escape,unescape解决中文乱码问题的方法
2010/05/26 Javascript
初窥JQuery(二)事件机制(2)
2010/12/06 Javascript
鼠标右击事件代码(asp.net后台)
2011/01/27 Javascript
$.format,jquery.format 使用说明
2011/07/13 Javascript
JS替换文本域内的回车示例
2014/02/18 Javascript
JS解析XML实例分析
2015/01/30 Javascript
jQuery实现的图文高亮滚动切换特效实例
2015/08/10 Javascript
BootStrap智能表单demo示例详解
2016/06/13 Javascript
给easyui datebox扩展一个清空的实例
2016/11/09 Javascript
javascript中递归的两种写法
2017/01/17 Javascript
jQuery插件echarts实现的多折线图效果示例【附demo源码下载】
2017/03/04 Javascript
JavaScript实现移动端轮播效果
2017/06/06 Javascript
Vue中错误图片的处理的实现代码
2019/11/07 Javascript
Vue实现购物小球抛物线的方法实例
2020/11/22 Vue.js
[01:05:29]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Aster BO3 第二场 1月24日
2021/03/11 DOTA
详谈Python2.6和Python3.0中对除法操作的异同
2017/04/28 Python
安装Python和pygame及相应的环境变量配置(图文教程)
2017/06/04 Python
Python微信企业号开发之回调模式接收微信端客户端发送消息及被动返回消息示例
2017/08/21 Python
Python实现压缩和解压缩ZIP文件的方法分析
2017/09/28 Python
浅谈python str.format与制表符\t关于中文对齐的细节问题
2019/01/14 Python
Python 按字典dict的键排序,并取出相应的键值放于list中的实例
2019/02/12 Python
Python两个字典键同值相加的几种方法
2019/03/05 Python
KLOOK客路:发现更好玩的世界,预订独一无二的旅行体验
2016/12/16 全球购物
印度尼西亚最大和最全面的网络商城:Blibli.com
2017/10/04 全球购物
新秀丽官方旗舰店:Samsonite拉杆箱、双肩包、皮具
2018/03/05 全球购物
Harrods美国:英国最大的百货公司
2018/11/04 全球购物
机械制造与自动化应届生求职信
2013/11/16 职场文书
面试自我评价范文
2014/09/17 职场文书
公安民警正风肃纪剖析材料
2014/10/10 职场文书
授权收款委托书范本
2014/10/10 职场文书
刑事申诉状范文
2015/05/20 职场文书