Python のマルチスレッド キューに問題があります。プロデューサーが入力キューから要素を取得し、いくつかの要素を生成して出力キューに配置し、コンシューマーが出力キューから要素を取得してそれらを出力するこのスクリプトがあります。
import threading
import Queue
class Producer(threading.Thread):
def __init__(self, iq, oq):
threading.Thread.__init__(self)
self.iq = iq
self.oq = oq
def produce(self, e):
self.oq.put(e*2)
self.oq.task_done()
print "Producer %s produced %d and put it to output Queue"%(self.getName(), e*2)
def run(self):
while 1:
e = self.iq.get()
self.iq.task_done()
print "Get %d from input Queue"%(e)
self.produce(e)
class Consumer(threading.Thread):
def __init__(self, oq):
threading.Thread.__init__(self)
self.oq = oq
def run(self):
while 1:
e = self.oq.get()
self.oq.task_done()
print "Consumer get %d from output queue and consumed"%e
iq = Queue.Queue()
oq = Queue.Queue()
for i in xrange(2):
iq.put((i+1)*10)
for i in xrange(2):
t1 = Producer(iq, oq)
t1.setDaemon(True)
t1.start()
t2 = Consumer(oq)
t2.setDaemon(True)
t2.start()
iq.join()
oq.join()
しかし、実行するたびに動作が異なります(例外が発生するか、消費者は何もしません)。問題は task_done() コマンドにあると思いますが、バグの場所を誰か説明してもらえますか?
Consumer クラスを変更しました。
class Consumer(threading.Thread):
def __init__(self, oq):
threading.Thread.__init__(self)
self.oq = oq
def run(self):
while 1:
e = self.oq.get()
self.oq.task_done()
print "Consumer get %d from output queue and consumed"%e
page = urllib2.urlopen("http://www.ifconfig.me/ip")
print page
各 task_done() コマンドの後のコンシューマは Web サイトに接続する必要があります (時間がかかります) が、そうではなく、代わりに task_done() の後のコードの実行時間が短い場合は実行されますが、長い場合は実行されません! なんで?誰でもこの問題を説明できますか? task_done() コマンドの前にすべてを配置すると、他のスレッドからキューをブロックしますが、これは十分に愚かです。または、Python でのマルチスレッド化について欠けているものはありますか?