为什么要引入线程池
如果在程序中经常要用到线程,频繁的创建和销毁线程会浪费很多硬件资源,
所以需要把线程和任务分离。线程可以反复利用,省去了重复创建的麻烦。
代码语言:javascript复制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
代码语言:javascript复制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("秒杀活动已经结束")