""" This is a simple example of the Producer/Consumer problem in Python. It makes use of threads and locks. """ from __future__ import with_statement from threading import Lock, Thread import time class Buffer(object): def __init__(self): """The buffer object. We simulate part of the Queue's public API.""" self._list = list() self._lock = Lock() # used to lock on the non-threadsafe data structures def get(self): # with is a new python 2.5 keyword. # The lock will be released automatically with self._lock: return self._list.pop() def put(self, val): with self._lock: self._list.append(val) def qsize(self): return len(self._list) class Producer(Thread): def __init__(self, buffer, name, limit=10): """The producer. buffer is the Queue object holding the produced values. name is simply the name of the thread. limit is the number of values to produce.""" self.buffer = buffer self.limit = limit Thread.__init__(self, name=name) def run(self): """The thread entry point. Here we put in the buffer one value at the time and we sleep to simulate the production.""" for i in range(self.limit): self.buffer.put(i) # it blocks until there's room for the value time.sleep(1) print "%s has put %d in the buffer." % (self.getName(), i) class Consumer(Thread): def __init__(self, buffer, name): """The consumer. buffer is the Queue object holding the values to be consumed. name is the name of the thread. """ self.buffer = buffer Thread.__init__(self, name=name) def run(self): """The thread entry point. Here we iterate on the buffer values and get them out from there.""" while self.buffer.qsize(): data = self.buffer.get() # it blocks until some value is available time.sleep(1) print "%s has got %d from the buffer." % (self.getName(), data) def main(): buffer = Buffer() # we create a single buffer shared among both threads prod = Producer(buffer, "Producer") cons = Consumer(buffer, "Consumer") prod.start(); cons.start(); if __name__ == '__main__': main()