使用锁的方式创建一个生产者与消费者
一、关于生产者与消费者的理解
- 1、生产者与消费者可以是多个(多线程),也可以是单个(单线程)
- 2、生产者是生产、创造、产生东西、数据、任务
- 3、消费者是消费生产者产出的东西
- 4、生产者与消费者之间创建连接,是通过生产者生产的东西,放到一个全局变量(类似仓库的地方),消费者直接去里面获取消费
- 5、简单点:生产者不停的往仓库放东西,消费者不停的从仓库拿走东西
二、定义一个生产者与消费者(生产包子与吃包子的案例)
1、导包及定义线程锁
import time import random import threading # 定义仓库里面多少包子 gBum = 100 # 创建一把锁 gLock = threading.Lock()
2、定义生产者类
class Producer(threading.Thread): """ 定义一个生产者,来生产包子,在生产过程中上锁不销售 """ def run(self): global gBum while True: gLock.acquire() bum = random.randint(0, 10) gBum += bum gLock.release() print('{0}生产了:{1}个包子,还剩余:{2}个包子'.format(threading.current_thread(), bum, gBum)) # 休眠时间,可以理解为生产包子需要时间 time.sleep(random.randrange(3))
3、定义消费者类
class Consumer(threading.Thread): """ 定义一个消费者的类,来消费包子 """ def run(self): global gBum while True: bum = random.randint(0, 10) gLock.acquire() if gBum > bum: gBum -= bum print("{0}在消费包子,消费了{1}个,还剩余{2}".format(threading.current_thread(), bum, gBum)) else: print("{0}在消费包子,消费了{1}个,但是包子数量不够,还剩余{2}".format(threading.current_thread(), bum, gBum)) gLock.release() # 休眠时间,可以理解为消费包子需要时间 time.sleep(random.randrange(3))
4、开启线程执行代码
if __name__ == '__main__': # # 启动八个消费者线程 for x in range(8): t = Consumer(name='消费者线程%d' % x) t.start() # 启动三个生产者 for x in range(3): t = Producer(name='生产者%d' % x) t.start()
5、打印信息(可以看到线程之间在不停的切换)
<Producer(生产者2, started 123145628491776)>生产了:2个包子,还剩余:18个包子 <Consumer(消费者线程0, started 123145575940096)>在消费包子,消费了4个,还剩余14 <Consumer(消费者线程3, started 123145591705600)>在消费包子,消费了5个,还剩余9 <Consumer(消费者线程4, started 123145596960768)>在消费包子,消费了0个,还剩余9 <Consumer(消费者线程2, started 123145586450432)>在消费包子,消费了9个,但是包子数量不够,还剩余9 <Consumer(消费者线程6, started 123145607471104)>在消费包子,消费了7个,还剩余2 <Consumer(消费者线程6, started 123145607471104)>在消费包子,消费了10个,但是包子数量不够,还剩余2 <Consumer(消费者线程1, started 123145581195264)>在消费包子,消费了10个,但是包子数量不够,还剩余2 <Producer(生产者0, started 123145617981440)>生产了:9个包子,还剩余:11个包子 <Producer(生产者0, started 123145617981440)>生产了:8个包子,还剩余:19个包子 <Producer(生产者0, started 123145617981440)>生产了:2个包子,还剩余:21个包子 <Producer(生产者0, started 123145617981440)>生产了:7个包子,还剩余:28个包子
三、添加条件来退出多线程
import time
import random
import threading
# 定义仓库里面多少包子
gBum = 100
# 总共生产多少次
gTotalTimes = 10
# 定义当前的
gTimes = 0
# 创建一把锁
gLock = threading.Lock()
class Producer(threading.Thread):
"""
定义一个生产者,来生产包子,在生产过程中上锁不销售
"""
def run(self):
global gBum
global gTotalTimes
global gTimes
while True:
gLock.acquire()
bum = random.randint(0, 10)
# 当生产大于指定的次数的时候退出线程
if gTimes >= gTotalTimes:
gLock.release()
break
gBum += bum
gTimes += 1
gLock.release()
print('{0}生产了:{1}个包子,还剩余:{2}个包子'.format(threading.current_thread(), bum, gBum))
# 休眠时间,可以理解为生产包子需要时间
time.sleep(random.randrange(3))
class Consumer(threading.Thread):
"""
定义一个消费者的类,来消费包子
"""
def run(self):
global gBum
global gTotalTimes
global gTimes
while True:
bum = random.randint(0, 10)
gLock.acquire()
if gBum > bum:
gBum -= bum
print("{0}在消费包子,消费了{1}个,还剩余{2}".format(threading.current_thread(), bum, gBum))
else:
# 当包子不足的时候且当前数大于总共生产次数的时候退出线程
if gTimes >= gTotalTimes:
print("{0}在消费包子,消费了{1}个,但是包子数量不够,还剩余{2}".format(threading.current_thread(), bum, gBum))
gLock.release()
break
gLock.release()
# 休眠时间,可以理解为消费包子需要时间
time.sleep(random.randrange(3))
if __name__ == '__main__':
# # 启动八个消费者线程
for x in range(8):
t = Consumer(name='消费者线程%d' % x)
t.start()
# 启动三个生产者
for x in range(3):
t = Producer(name='生产者%d' % x)
t.start()