在 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 相关文章推荐
tornado框架blog模块分析与使用
Nov 21 Python
python中合并两个文本文件并按照姓名首字母排序的例子
Apr 25 Python
在RedHat系Linux上部署Python的Celery框架的教程
Apr 07 Python
Diango + uwsgi + nginx项目部署的全过程(可外网访问)
Apr 22 Python
Python用for循环实现九九乘法表
May 31 Python
Python读写zip压缩文件的方法
Aug 29 Python
Python 中 function(#) (X)格式 和 (#)在Python3.*中的注意事项
Nov 30 Python
Python使用Beautiful Soup爬取豆瓣音乐排行榜过程解析
Aug 15 Python
python爬虫开发之Request模块从安装到详细使用方法与实例全解
Mar 09 Python
Python爬虫实例——scrapy框架爬取拉勾网招聘信息
Jul 14 Python
装上这 14 个插件后,PyCharm 真的是无敌的存在
Jan 11 Python
Python基础学习之奇异的GUI对话框
May 27 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实现的增强性mhash函数
2015/05/27 PHP
详解 PHP加密解密字符串函数附源码下载
2015/12/18 PHP
PHP编写RESTful接口的方法
2016/02/21 PHP
PHP设计模式之简单投诉页面实例
2016/02/24 PHP
PHP类相关知识点实例总结
2016/09/28 PHP
laravel 5.3中自定义加密服务的方案详解
2017/05/09 PHP
js 深拷贝函数
2008/12/04 Javascript
JavaScript 对象链式操作测试代码
2010/04/25 Javascript
给应用部分的js代码设定一个统一的入口
2014/06/15 Javascript
JavaScript日期时间与时间戳的转换函数分享
2015/01/31 Javascript
深入探寻seajs的模块化与加载方式
2015/04/14 Javascript
使用Sticky组件实现带sticky效果的tab导航和滚动导航的方法
2016/03/22 Javascript
AngularJs篇:使用AngularJs打造一个简易权限系统的实现代码
2016/12/26 Javascript
AngularJS实现使用路由切换视图的方法
2017/01/24 Javascript
vue.js利用Object.defineProperty实现双向绑定
2017/03/09 Javascript
Windows下使用Nodejs运行js的方法
2017/09/02 NodeJs
angular指令笔记ng-options的使用方法
2017/09/18 Javascript
vue-cli3.0 脚手架搭建项目的过程详解
2018/10/19 Javascript
vue 内置过滤器的使用总结(附加自定义过滤器)
2018/12/11 Javascript
Node.js API详解之 querystring用法实例分析
2020/04/29 Javascript
JS数组push、unshift、pop、shift方法的实现与使用方法示例
2020/04/29 Javascript
Vue获取微博授权URL代码实例
2020/11/04 Javascript
Python读写/追加excel文件Demo分享
2018/05/03 Python
解决安装python库时windows error5 报错的问题
2018/10/21 Python
Python实现Linux监控的方法
2019/05/16 Python
python config文件的读写操作示例
2019/09/27 Python
Python 多线程共享变量的实现示例
2020/04/17 Python
Python垃圾回收机制三种实现方法
2020/04/27 Python
Python装饰器结合递归原理解析
2020/07/02 Python
HTML5跳转小程序wx-open-launch-weapp的示例代码
2020/07/16 HTML / CSS
什么是唯一索引
2015/07/05 面试题
奶茶店创业计划书范文
2014/01/17 职场文书
教研活动总结
2014/04/28 职场文书
2016公司年会主持词
2015/07/01 职场文书
新学期家长寄语2016
2015/12/03 职场文书
Python可视化学习之seaborn调色盘
2022/02/24 Python