Python中的简单线程示例

时间:2014-03-30 17:51:19

标签: python multithreading producer-consumer

我对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" :)方式来做到这一点?

2 个答案:

答案 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()