在 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深入学习之上下文管理器
Aug 31 Python
python中的格式化输出用法总结
Jul 28 Python
Python递归函数定义与用法示例
Jun 02 Python
使用 Python 实现微信公众号粉丝迁移流程
Jan 03 Python
基于anaconda下强大的conda命令介绍
Jun 11 Python
python单例模式实例解析
Aug 28 Python
Django csrf 两种方法设置form的实例
Feb 03 Python
python3.6下Numpy库下载与安装图文教程
Apr 02 Python
Python reshape的用法及多个二维数组合并为三维数组的实例
Feb 07 Python
pandas中的数据去重处理的实现方法
Feb 10 Python
Python3如何判断三角形的类型
Apr 12 Python
基于Python下载网络图片方法汇总代码实例
Jun 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
PHP中error_reporting()函数的用法(修改PHP屏蔽错误)
2011/07/01 PHP
浅谈web上存漏洞及原理分析、防范方法(安全文件上存方法)
2013/06/29 PHP
PHP使用递归方式列出当前目录下所有文件的方法
2015/06/02 PHP
php实现图片缩略图的方法
2016/03/29 PHP
理解JavaScript中的事件
2006/09/23 Javascript
一个JS翻页效果
2007/07/23 Javascript
15 个 JavaScript Web UI 库
2010/05/19 Javascript
11款新鲜的jQuery插件[附所有demo下载]
2011/01/24 Javascript
JavaScript代码简单实现求杨辉三角给定行的最大值
2013/10/29 Javascript
js实现带搜索功能的下拉框实时搜索实时匹配
2013/11/05 Javascript
调整小数的格式保留小数点后两位
2014/05/14 Javascript
简述jQuery ajax的执行顺序
2016/01/05 Javascript
jQuery实现微信长按识别二维码功能
2016/08/26 Javascript
移动端滑动插件Swipe教程
2016/10/16 Javascript
微信小程序 参数传递实例代码
2017/03/20 Javascript
vue.js 使用v-if v-else发现没有执行解决办法
2017/05/15 Javascript
微信小程序 获取javascript 里的数据
2017/08/17 Javascript
LayerClose弹窗关闭刷新方法
2018/08/17 Javascript
JavaScript中BOM对象原理与用法分析
2019/07/09 Javascript
javascript实现异形滚动轮播
2019/11/28 Javascript
linux 下以二进制的方式安装 nodejs
2020/02/12 NodeJs
koa-passport实现本地验证的方法示例
2020/02/20 Javascript
JQuery省市联动效果实现过程详解
2020/05/08 jQuery
Vue实现图书管理案例
2021/01/20 Vue.js
Django在Win7下的安装及创建项目hello word简明教程
2014/07/14 Python
Python中的pprint折腾记
2015/01/21 Python
Python正则简单实例分析
2017/03/21 Python
详解将Django部署到Centos7全攻略
2018/09/26 Python
Series和DataFrame使用简单入门
2019/11/13 Python
python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析
2020/03/08 Python
详解Python中list[::-1]的几种用法
2020/11/16 Python
QQ空间主人寄语大全
2014/04/12 职场文书
财务会计岗位职责
2015/02/03 职场文书
小兵张嘎电影观后感
2015/06/03 职场文书
深入讲解数据库中Decimal类型的使用以及实现方法
2022/02/15 MySQL
Java 数据结构七大排序使用分析
2022/04/02 Java/Android