Monitor with wait/notifyAll
Time O(n) Space O(n) outputOne shared counter guarded by synchronized(this). Each thread loops: while it's not its turn and i ≤ n, wait; if i > n, exit; else write and notifyAll.
n = 5threads(map)
state(vars)
out(list)
Step 1/4i = 1 and 2 only match the number thread's test. The others call wait(), which releases the lock. The number thread writes 1, then 2, calling notifyAll after each.
import java.util.*;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
class Solution {
private int i = 1, n;
private final List<String> out = new ArrayList<>();
public List<String> fizzBuzz(int n) throws InterruptedException {
this.n = n;
Thread[] threads = {
new Thread(() -> run(x -> x % 15 == 0, x -> "fizzbuzz")),
new Thread(() -> run(x -> x % 3 == 0 && x % 5 != 0, x -> "fizz")),
new Thread(() -> run(x -> x % 5 == 0 && x % 3 != 0, x -> "buzz")),
new Thread(() -> run(x -> x % 3 != 0 && x % 5 != 0, String::valueOf)),
};
for (Thread t : threads) t.start();
for (Thread t : threads) t.join();
return out;
}
private void run(IntPredicate mine, IntFunction<String> text) {
synchronized (this) {
while (true) {
while (i <= n && !mine.test(i)) {
try { wait(); } catch (InterruptedException e) { return; }
}
if (i > n) { notifyAll(); return; }
out.add(text.apply(i));
i++;
notifyAll();
}
}
}
}Verdict: notifyAll is needed: four different conditions share one monitor.