版权声明:转载请声明出处,谢谢! https://blog.csdn.net/qq_31468321/article/details/83281098
python多线程之lock版生产者消费者模式,谨以此文记之。
python多线程技术,仁者见仁智者见智,有道其鸡肋,有道其乖张。暂且不去评论。本文仅述其浅浅的应用罢了。如下见祥例说明。
本文利用多线程技术,模拟在python爬虫环境中的应用,分为生产者部分和消费者部分,也就是将一个爬虫项目分为两个部分,获取将要爬的取详细信息的URL部分,和爬取该URL中的关键信息的部分。生产者模拟第一部分,消费者模拟第二部分。也就是说,生产者负责生成指定的详情页面的URL,消费者负责使用该URL,获取详细信息。
将整个场景模拟为赚钱和花钱。生产者赚钱,消费者花钱,当消费者发现金钱不够花的时候,跳过,等有钱的时候再花钱。(消费者模拟再爬虫项目未正式结束之前,生成URL的代码跟不上消费URL的代码的节奏时,跳过主要代码,等到生成了相关URL时,再继续执行)
代码实现:
首先,导入三个包,以下三个包,time用于延时,random生成随机数,threading用于创建线程
import time
import random
import threading
定义全局变量,在这里定义了一个全局锁,主要是为了避免在多个线程处理全局变量时,发生的紊乱问题。
gMoney = 1000 #设置初始金钱
gLock = threading.Lock()#创建全局锁
gTotletimes = 10 #定义生产者生产的总次数,模拟爬虫需要爬取URL的总数
gTimes = 0 #定义已经爬取的URL数
然后,创建生产者:在生产者中,随机生产money,将money添加到全局gMoney中,供消费者消费,相当于爬虫生产URL添加到全局URL列表中一样。
class Producter(threading.Thread):
def run(self):
global gMoney#声明全局变量
global gTimes
global gTotletimes
while True:
money = random.randint(100,1000)#生产随机数量的money
gLock.acquire()#开启锁
if gTimes >= gTotletimes:#判断是否完成生产任务,如果完成则跳出,释放锁
gLock.release()
break
gTimes += 1
gMoney += money#将生产的金钱添加到全局变量中
print("%s生产者生产了%d元钱,总共有%d元钱"%(threading.current_thread(),money,gMoney))
gLock.release()#释放锁
time.sleep(0.2)
创建消费者,随机产生需要消费的金额,如果全局变量中的金额足够,则消费,否则等待再消费。
class Consumer(threading.Thread):
def run(self):
global gMoney
global gTimes
global gTotletimes
while True:
money = random.randint(100,1000)#生成需要消费的金额
gLock.acquire()
if money <= gMoney:#如果金钱足够,则消费
gMoney -= money
print("{}消费者消费了{}元钱,还有{}元钱".format(threading.current_thread(),money,gMoney))
else:
if gTimes >= gTotletimes:#如果生产者不在生产,金钱也不够消费,则退出
gLock.release()
break
print("消费者%s准备消费%d元钱,不足"%(threading.current_thread(),money))
gLock.release()
time.sleep(0.2)
如下为主函数:
def main():
for i in range(3):#生成3个消费者
t2 = Consumer(name='消费者%d'%(i))
t2.start()
for x in range(3):#生成3个生产者
t1 = Producter(name='生产者{}'.format(x))
t1.start()
if __name__ == '__main__':
main()
运行如下:
生产者生产了10次,消费着在整体程序未运行结束时,有一次不足,等待之后在次消费。
结束