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()
######运行结果######
:一支穿云箭 西米:千军万马来相见 :山无棱,天地合,乃敢与君绝! 西米:海可枯,石可烂,激情永不散! :紫薇!!!!(此处图片省略) 西米:尔康!!!(此处图片省略) :是你 西米:是我 :有钱吗借点 西米:滚