我对Python中的线程有疑问(我承认,我是这个主题的新手)。
我有对象,我想在方法part1()(有一些随机时间间隔)和part2()中生成数字列表 - 打印ASAP所有生成的数字。
这是我的代码:
import random
import time
from threading import Thread
class GenerateRand:
def __init__(self):
self.h = []
def part1(self):
while True:
r = random.choice(range(9))
self.h.append(r)
print "Rand in list:", self.h
time.sleep(random.randint(1, 100)/100.0)
def part2(self):
while True:
if self.h:
print "Get:", self.h.pop()
if __name__ == "__main__":
obj = GenerateRand()
th1 = Thread(target = obj.part1)
th2 = Thread(target = obj.part2)
th1.start()
th2.start()
th1.join()
th2.join()
这很好用,但是来自线程的打印是混合的。这段代码好吗? 有没有更好的(" pythonic" :)方式来做到这一点?
答案 0 :(得分:2)
这是一个经典的producer-consumer问题。最好使用Queue
在线程之间传递消息(在您的情况下消息是r
中的随机数),以避免繁忙等待,这会消耗不必要的CPU时间。 Queue.get()
允许等待下一条消息非常繁忙。
除此之外,你的解决方案很好。这正是你如何实现这样的流程。我个人更喜欢继承threading.Thread
而不是使用target
参数,但对于简单的情况,使用target
很好。 (more details here)。
当然可以将打印输出“混合”。打印命令输出到同一位置(stdout),并且不保证执行它们的顺序。毕竟,他们是不同的线程......
答案 1 :(得分:2)
如果您想避免文本输出被扰乱,可以为类添加锁
class GenerateRand:
def __init__(self):
self.h = []
self.lock = threading.Lock()
def part1(self):
while True:
r = random.choice(range(9))
self.lock.acquire()
self.h.append(r)
print("added: " + str(self.h))
self.lock.release()
time.sleep(random.randint(1,100)/100.0)
def part2(self):
while True:
if self.h:
self.lock.acquire()
print( "popped: " + str( self.h.pop()))
self.lock.release()