Python中使用Queue和Condition进行线程同步的方法
Queue模块保持线程同步
利用Queue对象先进先出的特性,将每个生产者的数据一次存入队列,而每个消费者将依次从队列中取出数据
importthreading#导入threading模块 importQueue#导入Queue模块 classProducer(threading.Thread):#定义生产者类 def__init__(self,threadname): threading.Thread.__init__(self,name=threadname) defrun(self): globalqueue#声明queue为全局变量 queue.put(self.getName())#调用put方法将线程名添加到队列中 printself.getName(),'put',self.getName(),'toqueue' classConsumer(threading.Thread):#定义消费者类 def__init__(self,threadname): threading.Thread.__init__(self,name=threadname) defrun(self): globalqueue printself.getName(),'get',queue.get(),'fromqueue'#调用get方法获取队列中内容 queue=Queue.Queue()#生成队列对象 plist=[]#生成者对象列表 clist=[]#消费者对象列表 foriinrange(10): p=Producer('Producer'+str(i)) plist.append(p)#添加到生产者对象列表 foriinrange(10): c=Consumer('Consumer'+str(i)) clist.append(c)#添加到消费者对象列表 foriinplist: i.start()#运行生产者线程 i.join() foriinclist: i.start()#运行消费者线程 i.join() ######运行结果###### >>>Producer0putProducer0toqueue Producer1putProducer1toqueue Producer2putProducer2toqueue Producer3putProducer3toqueue Producer4putProducer4toqueue Producer5putProducer5toqueue Producer6putProducer6toqueue Producer7putProducer7toqueue Producer8putProducer8toqueue Producer9putProducer9toqueue Consumer0getProducer0fromqueue Consumer1getProducer1fromqueue Consumer2getProducer2fromqueue Consumer3getProducer3fromqueue Consumer4getProducer4fromqueue Consumer5getProducer5fromqueue Consumer6getProducer6fromqueue Consumer7getProducer7fromqueue Consumer8getProducer8fromqueue Consumer9getProducer9fromqueue
Condition实现复杂的同步
使用Condition对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition除了具有Lock对象的acquire方法和release方法外,
还有wait方法,notify方法,notifyAll方法等用于条件处理。
条件变量保持线程同步:threading.Condition()
- wait():线程挂起,直到收到一个notify通知才会被唤醒继续运行
- notify():通知其他线程,那些挂起的线程接到这个通知之后会开始运行
- notifyAll():如果wait状态线程比较多,notifyAll的作用就是通知所有线程(这个一般用得少)
#coding:utf-8 importthreading importtime cond=threading.Condition() classkongbaige(threading.Thread): def__init__(self,cond,diaosiname): threading.Thread.__init__(self,name=diaosiname) self.cond=cond defrun(self): self.cond.acquire()#获取锁 printself.getName()+':一支穿云箭'#空白哥说的第一句话 self.cond.notify()#唤醒其他wait状态的线程(通知西米哥让他说话) #然后进入wait线程挂起状态等待notify通知(等西米哥的回复,接下来俩人就开始扯蛋) self.cond.wait() printself.getName()+':山无棱,天地合,乃敢与君绝!' self.cond.notify() self.cond.wait() printself.getName()+':紫薇!!!!(此处图片省略)' self.cond.notify() self.cond.wait() printself.getName()+':是你' self.cond.notify() self.cond.wait() #这里是空白哥说的最后一段话,接下来就没有对白了 printself.getName()+':有钱吗借点' self.cond.notify()#通知西米哥 self.cond.release()#释放锁 classximige(threading.Thread): def__init__(self,cond,diaosiname): threading.Thread.__init__(self,name=diaosiname) self.cond=cond defrun(self): self.cond.acquire() self.cond.wait()#线程挂起(等西米哥的notify通知) printself.getName()+':千军万马来相见' self.cond.notify()#说完话了notify空白哥wait的线程 self.cond.wait()#线程挂起等待空白哥的notify通知 printself.getName()+':海可枯,石可烂,激情永不散!' self.cond.notify() self.cond.wait() printself.getName()+':尔康!!!(此处图片省略)' self.cond.notify() self.cond.wait() printself.getName()+':是我' self.cond.notify() self.cond.wait() #这里是最后一段话,后面空白哥没接话了所以说完就释放锁结束线程 printself.getName()+':滚' self.cond.release() kongbai=kongbaige(cond,'') ximi=ximige(cond,'西米') #尼玛下面这2个启动标志是关键,虽然是空白哥先开的口,但是不能让他先启动, #因为他先启动的可能直到发完notify通知了,西米哥才开始启动, #西米哥启动后会一直处于44行的wait状态,因为空白哥已经发完notify通知了进入wait状态了, #而西米哥没收到 #造成的结果就是2根线程就一直在那挂起,什么都不干,也不扯蛋了 ximi.start() kongbai.start()
######运行结果######
:一支穿云箭 西米:千军万马来相见 :山无棱,天地合,乃敢与君绝! 西米:海可枯,石可烂,激情永不散! :紫薇!!!!(此处图片省略) 西米:尔康!!!(此处图片省略) :是你 西米:是我 :有钱吗借点 西米:滚