在 Python 中利用Pool 进行多处理
作者:宇宙之一粟 发布时间:2022-03-07 13:10:36
为什么要引入线程池
如果在程序中经常要用到线程,频繁的创建和销毁线程会浪费很多硬件资源,
所以需要把线程和任务分离。线程可以反复利用,省去了重复创建的麻烦。
在 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("秒杀活动已经结束")
来源:https://blog.51cto.com/yuzhou1su/5200609


猜你喜欢
- 1、一个或多个文件夹组成一个模块,而一个模块组合构成了一个包发布在公共目录里。2、包必须有__init__文件,否则就是一个文件夹。实例im
- 二次移动平均法逻辑二次移动平均法是一种重要的数学工具,用于处理时间序列数据,它的主要目的是通过平滑序列中的噪音数据来更好地捕捉趋势。具体实现
- 前言我们经常会有这样的需求,比如评论功能,每个评论都有可能会有自己的子评论,如果在界面只展示成一列的话非常不美观,也不能体现出他们的层级关系
- 一、前言为方便描述教程例子,这里给出mysql表结构定义和golang结构体定义。下面是教程用到的foods表结构定义:CREATE TAB
- 在网上有很多文章介绍数据库优化知识,但是大部份文章只是对某个一个方面进行说明,而对于我们程序员来说这种介绍并不能很好的掌握优化知识,因为很多
- Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分。文本总是Unicode,由str类型表示,二进制数据则由bytes
- 前言django是python语言的一个web框架,功能强大。配合一些插件可为web网站很方便地添加搜索功能。搜索引擎使用whoosh,是一
- 本文实例讲述了Javascript与PHP验证用户输入URL地址是否正确的方法,分享给大家供大家参考。具体方法如下:1.javascript
- 内部/内嵌函数1、定义:在一个函数的函数体内使用关键字def关键字定义一个新的函数,这个新的函数就叫做内部/内嵌函数。2、注意点:内部函数的
- 一基础理解: var e = document.getElementById("selectId");e. option
- lambda/filter/map/reduce这几个函数面试中很肯定会用到,本篇主要介绍这几个函数的用法。1 lambda匿名函数,用法如
- 常规循环引用内存泄漏和Closure内存泄漏 要了解javascript的内存泄漏问题,首先要了解的就是javascript的GC原理。我记
- 一、python读取和写入文件内容任务:在cmd默认登陆目录中建立一个命名为test.txt的文件并写入内容“welco
- 我就废话不多说了,直接上代码吧!import paramikoimport pymysqlimport timelinux = ['
- 简介想写一个登录注册的demo,但是以前的demo数据都写在程序里面,每一关掉程序数据就没保存住。。于是想着写到配置文件里好了Python自
- 大家好,本期给大家带来Python字典11个方法的全面解析,希望对你有所帮助。字典(Dictionary)是Python提供的一种常用的数据
- 我们用pycharm写CSS的时候,是不是苦于没有提示,那么pycharm中如何显示CSS提示呢?下面小编给大家分享一下。首先点击左上角的f
- 环境介绍python3.8numpymatplotlib第一步,绘制一个三维的爱心关于这一步,我采用的是大佬博客中的最后一种绘制方法。当然,
- Anaconda是Python的一个开源发行版本,主要面向科学计算,预装了丰富强大的库。使用Anaconda可以轻松管理多个版本的Pytho
- 概述具体的案例描述在此就不多赘述. 同一数据集我们在机器学习里的随机森林模型中已经讨论过.导包import numpy as npimpor