Skip to content

Instantly share code, notes, and snippets.

@ckhung
Last active May 13, 2021 03:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ckhung/c5c155836e9485bb85e42d4f41027676 to your computer and use it in GitHub Desktop.
Save ckhung/c5c155836e9485bb85e42d4f41027676 to your computer and use it in GitHub Desktop.
multiple producers and multiple consumers working on the same queue
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# slightly modified from https://stackoverflow.com/questions/53778588/two-condition-variables-attached-to-the-same-lock-different-behaviors-in-python
# 也請見 「概念性、宏觀視野的程序/執行緒同步機制總覽」
# https://newtoypia.blogspot.com/2017/12/synchronization.html
# Note: pip3 install colored
from threading import Thread, Lock, Condition
import time
from random import random, randint
import colored
from colored import stylize
queue = []
CAPACITY = 3
qlock = Lock()
item_ok = Condition(qlock)
space_ok = Condition(qlock)
class ProducerThread(Thread):
def run(self):
global queue
mycolor = self.name
while True:
qlock.acquire()
while len(queue) >= CAPACITY:
print(stylize('queue is full, stop producing', colored.fg(mycolor)))
space_ok.wait()
if len(queue) >= CAPACITY:
print(stylize('oops, someone filled the space before me', colored.fg(mycolor)))
item = chr(ord('A')+randint(0,25))
print(stylize('['+' '.join(queue)+'] <= '+item, colored.fg( mycolor)))
queue.append(item)
item_ok.notify()
qlock.release()
time.sleep((random()+1)*1.5)
class ConsumerThread(Thread):
def run(self):
global queue
mycolor = self.name
while True:
qlock.acquire()
while not queue:
print(stylize('queue is empty, stop consuming', colored.fg(mycolor)))
item_ok.wait()
if not queue:
print(stylize('oops, someone consumed the food before me', colored.fg(mycolor)))
item = queue.pop(0)
print(stylize(item+' <= ['+' '.join(queue)+']', colored.fg( mycolor)))
space_ok.notify()
qlock.release()
time.sleep((random()+1)*1.5)
ProducerThread(name='red', daemon=True).start()
ProducerThread(name='green', daemon=True).start()
ProducerThread(name='blue', daemon=True).start()
ConsumerThread(name='cyan', daemon=True).start()
ConsumerThread(name='magenta', daemon=True).start()
ConsumerThread(name='yellow', daemon=True).start()
try:
while True:
time.sleep(3)
except KeyboardInterrupt:
print("Exiting")
@ckhung
Copy link
Author

ckhung commented Dec 26, 2018

多個 producers 多個 consumers 的 python 程式。 注意: 本程式要用 python3 執行。 執行前請先以 pip3 install colored 安裝相依套件。 詳見 概念性、宏觀視野的程序/執行緒同步機制總覽。 感謝 stackoverflow 網友 Felix 的協助

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment