Fizz Buzz Multithreaded
Created: April 6, 2020 by [lek-tin]
Last updated: April 6, 2020
Write a program that outputs the string representation of numbers from 1
to n
, however:
- If the number is divisible by 3, output
"fizz"
. - If the number is divisible by 5, output
"buzz"
. - If the number is divisible by both 3 and 5, output
"fizzbuzz"
.
For example, for n = 15
, we output: 1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz.
Suppose you are given the following code:
class FizzBuzz {
public FizzBuzz(int n) { ... } // constructor
public void fizz(printFizz) { ... } // only output "fizz"
public void buzz(printBuzz) { ... } // only output "buzz"
public void fizzbuzz(printFizzBuzz) { ... } // only output "fizzbuzz"
public void number(printNumber) { ... } // only output the numbers
}
Implement a multithreaded version of FizzBuzz
with four threads. The same instance of FizzBuzz
will be passed to four different threads:
- Thread A will call
fizz()
to check for divisibility of 3 and outputsfizz
. - Thread B will call
buzz()
to check for divisibility of 5 and outputsbuzz
. - Thread C will call
fizzbuzz()
to check for divisibility of 3 and 5 and outputs fizzbuzz. - Thread D will call
number()
which should only output the numbers.
Solution
import threading
class FizzBuzz:
def __init__(self, n: int):
self.funcNum = 4
self.n = n
self.curr = 0
self.cv = threading.Condition()
# printFizz() outputs "fizz"
def fizz(self, printFizz: 'Callable[[], None]') -> None:
for i in range(1, self.n+1):
with self.cv:
# wait for the printFizz lock to UNLOCK
while self.curr % self.funcNum != 0:
self.cv.wait()
self.curr += 1
if i % 3 == 0 and i % 5 != 0:
printFizz()
# notify printBuzz, printFizzBuzz, printNumber that the printFizz lock has been UNLOCKED
self.cv.notify_all()
# printBuzz() outputs "buzz"
def buzz(self, printBuzz: 'Callable[[], None]') -> None:
for i in range(1, self.n+1):
with self.cv:
# wait for the printBuzz lock to UNLOCK
while self.curr % self.funcNum != 1:
self.cv.wait()
self.curr += 1
if i % 3 != 0 and i % 5 == 0:
printBuzz()
# notify printFizz, printFizzBuzz, printNumber that the printBuzz lock has been UNLOCKED
self.cv.notify_all()
# printFizzBuzz() outputs "fizzbuzz"
def fizzbuzz(self, printFizzBuzz: 'Callable[[], None]') -> None:
for i in range(1, self.n+1):
with self.cv:
# wait for the fizzbuzz lock to UNLOCK
while self.curr % self.funcNum != 2:
self.cv.wait()
self.curr += 1
if i % 3 == 0 and i % 5 == 0:
printFizzBuzz()
# notify printFizz, printBuzz, printNumber that the printFizzBuzz lock has been UNLOCKED
self.cv.notify_all()
# printNumber(x) outputs "x", where x is an integer.
def number(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(1, self.n+1):
with self.cv:
# wait for the printNumber lock to UNLOCK
while self.curr % self.funcNum != 3:
self.cv.wait()
self.curr += 1
if i % 3 != 0 and i % 5 != 0:
printNumber(i)
# notify printFizz, printBuzz, printFizzBuzz that the printNumber lock has been UNLOCKED
self.cv.notify_all()