Fizz Buzz Multithreaded
Problem
You have a class with four functions running on separate threads for numbers 1..n: fizz() prints "fizz" when a number is divisible by 3 (and not 5), buzz() prints "buzz" when divisible by 5 (and not 3), fizzbuzz() prints "fizzbuzz" when divisible by both 3 and 5, and number() prints the value otherwise. The four threads run concurrently, but the combined output must equal the single-threaded FizzBuzz sequence for 1..n.
n = 51, 2, fizz, 4, buzzfrom threading import Lock
class FizzBuzz:
def __init__(self, n):
self.n = n
self.cur = 1
self.lock = Lock()
def _try(self, want, do):
while True:
with self.lock:
if self.cur > self.n:
return
d3 = self.cur % 3 == 0
d5 = self.cur % 5 == 0
kind = "fb" if d3 and d5 else "f" if d3 else "b" if d5 else "n"
if kind == want:
do(self.cur)
self.cur += 1
def fizz(self, printFizz):
self._try("f", lambda x: printFizz())
def buzz(self, printBuzz):
self._try("b", lambda x: printBuzz())
def fizzbuzz(self, printFizzBuzz):
self._try("fb", lambda x: printFizzBuzz())
def number(self, printNumber):
self._try("n", lambda x: printNumber(x))
class FizzBuzz {
constructor(n) {
this.n = n;
this.cur = 1;
}
kind(x) {
const d3 = x % 3 === 0, d5 = x % 5 === 0;
return d3 && d5 ? "fb" : d3 ? "f" : d5 ? "b" : "n";
}
// Each thread loops, acting only on its own turn.
step(want, emit) {
while (this.cur <= this.n) {
if (this.kind(this.cur) === want) {
emit(this.cur);
this.cur++;
}
}
}
fizz(printFizz) { this.step("f", () => printFizz()); }
buzz(printBuzz) { this.step("b", () => printBuzz()); }
fizzbuzz(printFizzBuzz) { this.step("fb", () => printFizzBuzz()); }
number(printNumber) { this.step("n", (x) => printNumber(x)); }
}
import java.util.concurrent.Semaphore;
class FizzBuzz {
private int n;
private int cur = 1;
private final Object lock = new Object();
public FizzBuzz(int n) { this.n = n; }
private String kind(int x) {
boolean d3 = x % 3 == 0, d5 = x % 5 == 0;
return d3 && d5 ? "fb" : d3 ? "f" : d5 ? "b" : "n";
}
private void run(String want, Runnable doIt) {
while (true) {
synchronized (lock) {
if (cur > n) return;
if (kind(cur).equals(want)) { doIt.run(); cur++; }
}
}
}
public void fizz(Runnable printFizz) { run("f", printFizz); }
public void buzz(Runnable printBuzz) { run("b", printBuzz); }
public void fizzbuzz(Runnable printFizzBuzz) { run("fb", printFizzBuzz); }
public void number(java.util.function.IntConsumer printNumber) {
while (true) {
synchronized (lock) {
if (cur > n) return;
if (kind(cur).equals("n")) { printNumber.accept(cur); cur++; }
}
}
}
}
#include <mutex>
#include <functional>
class FizzBuzz {
int n, cur = 1;
std::mutex m;
std::string kind(int x) {
bool d3 = x % 3 == 0, d5 = x % 5 == 0;
return d3 && d5 ? "fb" : d3 ? "f" : d5 ? "b" : "n";
}
void run(const std::string& want, std::function<void(int)> emit) {
while (true) {
std::lock_guard<std::mutex> g(m);
if (cur > n) return;
if (kind(cur) == want) { emit(cur); cur++; }
}
}
public:
FizzBuzz(int n) : n(n) {}
void fizz(std::function<void()> pf) { run("f", [&](int){ pf(); }); }
void buzz(std::function<void()> pb) { run("b", [&](int){ pb(); }); }
void fizzbuzz(std::function<void()> pfb) { run("fb", [&](int){ pfb(); }); }
void number(std::function<void(int)> pn) { run("n", pn); }
};
Explanation
Four threads each want to print part of the FizzBuzz sequence, but they must take turns so the output stays in order. The idea is a single shared counter cur plus a lock so only one thread touches it at a time.
Every thread runs the same loop in _try: grab the lock, look at the current number, and figure out its kind — is it a fizz, a buzz, a fizzbuzz, or a plain number? A thread only acts when the kind matches the one it is responsible for.
If it is this thread's turn, it prints its word and then does self.cur += 1 to advance to the next number. Otherwise it releases the lock and loops again, letting the eligible thread get its turn. This is why no thread ever prints out of order.
The loop ends for everyone once cur > n: each thread sees the bound and returns.
Example with n = 5: at cur=3 only fizz() matches, so it prints "fizz" and bumps cur to 4; at cur=5 only buzz() matches, giving the final sequence 1, 2, fizz, 4, buzz.