我们将使用Python线程来解决Python中的生产者—消费者问题。这个问题完全不像他们在学校中说的那么难。
如果你对生产者—消费者问题有了解,看这篇博客会更有意义。
为什么要关心生产者—消费者问题:
当我们在使用线程时,你可以学习以下的线程概念:
我假设你已经有这些基本概念:线程、竞态条件,以及如何解决静态条件(例如使用lock)。否则的话,你建议你去看我上一篇文章basics of Threads。
引用维基百科:
生产者的工作是产生一块数据,放到buffer中,如此循环。与此同时,消费者在消耗这些数据(例如从buffer中把它们移除),每次一块。
这里的关键词是“同时”。所以生产者和消费者是并发运行的,我们需要对生产者和消费者做线程分离。
123456789 | from threading import Thread class ProducerThread(Thread): def run(self): pass class ConsumerThread(Thread): def run(self): pass |
再次引用维基百科:
这个为描述了两个共享固定大小缓冲队列的进程,即生产者和消费者。
假设我们有一个全局变量,可以被生产者和消费者线程修改。生产者产生数据并把它加入到队列。消费者消耗这些数据(例如把它移出)。
1 | queue = [] |
在刚开始,我们不会设置固定大小的条件,而在实际运行时加入(指下述例子)。
一开始带bug的程序:
123456789101112131415161718192021222324252627282930313233 | from threading import Thread, Lockimport timeimport random queue = []lock = Lock() class ProducerThread(Thread): def run(self): nums = range(5) #Will create the list [0, 1, 2, 3, 4] global queue while True: num = random.choice(nums) #Selects a random number from list [0, 1, 2, 3, 4] lock.acquire() queue.append(num) print \”Produced\”, num lock.release() time.sleep(random.random()) class ConsumerThread(Thread): def run(self): global queue while True: lock.acquire() if not queue: print \”Nothing in queue, but consumer will try to consume\” num = queue.pop(0) print \”Consumed\”, num lock.release() time.sleep(random.random()) ProducerThread().start()ConsumerThread().start() |
运行几次并留意一下结果。如果程序在IndexError异常后并没有自动结束,用Ctrl+Z结束运行。
样例输出:
1234567891011121314 | Produced 3Consumed 3Produced 4Consumed 4Produced 1Consumed 1Nothing in queue, but consumer will try to consumeException in thread Thread–2:Traceback (most recent call last): File \”/usr/lib/python2.7/threading.py\”, line 551, in __bootstrap_inner self.run() File \”producer_consumer.py\”, line 31, in run num =-h\”> 31, in run num =Ό全不像他们在学校中说的那么难。
如果你对生产者—消费者问题有了解,看这篇博客会更有意义。 为什么要关心生产者—消费者问题:
当我们在使用线程时,你可以学习以下的线程概念:
我假设你已经有这些基本概念:线程、竞态条件,以及如何解决静态条件(例如使用lock)。否则的话,你建议你去看我上一篇文章basics of Threads。 引用维基百科: 生产者的工作是产生一块数据,放到buffer中,如此循环。与此同时,消费者在消耗这些数据(例如从buffer中把它们移除),每次一块。 这里的关键词是“同时”。所以生产者和消费者是并发运行的,我们需要对生产者和消费者做线程分离。
再次引用维基百科: 这个为描述了两个共享固定大小缓冲队列的进程,即生产者和消费者。 假设我们有一个全局变量,可以被生产者和消费者线程修改。生产者产生数据并把它加入到队列。消费者消耗这些数据(例如把它移出)。
在刚开始,我们不会设置固定大小的条件,而在实际运行时加入(指下述例子)。 一开始带bug的程序:
运行几次并留意一下结果。如果程序在IndexError异常后并没有自动结束,用Ctrl+Z结束运行。 样例输出:
|