comments | difficulty | edit_url | tags | |
---|---|---|---|---|
true |
Medium |
|
You have the four functions:
printFizz
that prints the word"fizz"
to the console,printBuzz
that prints the word"buzz"
to the console,printFizzBuzz
that prints the word"fizzbuzz"
to the console, andprintNumber
that prints a given integer to the console.
You are given an instance of the class FizzBuzz
that has four functions: fizz
, buzz
, fizzbuzz
and number
. The same instance of FizzBuzz
will be passed to four different threads:
- Thread A: calls
fizz()
that should output the word"fizz"
. - Thread B: calls
buzz()
that should output the word"buzz"
. - Thread C: calls
fizzbuzz()
that should output the word"fizzbuzz"
. - Thread D: calls
number()
that should only output the integers.
Modify the given class to output the series [1, 2, "fizz", 4, "buzz", ...]
where the ith
token (1-indexed) of the series is:
"fizzbuzz"
ifi
is divisible by3
and5
,"fizz"
ifi
is divisible by3
and not5
,"buzz"
ifi
is divisible by5
and not3
, ori
ifi
is not divisible by3
or5
.
Implement the FizzBuzz
class:
FizzBuzz(int n)
Initializes the object with the numbern
that represents the length of the sequence that should be printed.void fizz(printFizz)
CallsprintFizz
to output"fizz"
.void buzz(printBuzz)
CallsprintBuzz
to output"buzz"
.void fizzbuzz(printFizzBuzz)
CallsprintFizzBuzz
to output"fizzbuzz"
.void number(printNumber)
Callsprintnumber
to output the numbers.
Example 1:
Input: n = 15 Output: [1,2,"fizz",4,"buzz","fizz",7,8,"fizz","buzz",11,"fizz",13,14,"fizzbuzz"]
Example 2:
Input: n = 5 Output: [1,2,"fizz",4,"buzz"]
Constraints:
1 <= n <= 50
class FizzBuzz {
private int n;
public FizzBuzz(int n) {
this.n = n;
}
private Semaphore fSema = new Semaphore(0);
private Semaphore bSema = new Semaphore(0);
private Semaphore fbSema = new Semaphore(0);
private Semaphore nSema = new Semaphore(1);
// printFizz.run() outputs "fizz".
public void fizz(Runnable printFizz) throws InterruptedException {
for (int i = 3; i <= n; i = i + 3) {
if (i % 5 != 0) {
fSema.acquire();
printFizz.run();
nSema.release();
}
}
}
// printBuzz.run() outputs "buzz".
public void buzz(Runnable printBuzz) throws InterruptedException {
for (int i = 5; i <= n; i = i + 5) {
if (i % 3 != 0) {
bSema.acquire();
printBuzz.run();
nSema.release();
}
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
for (int i = 15; i <= n; i = i + 15) {
fbSema.acquire();
printFizzBuzz.run();
nSema.release();
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void number(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
nSema.acquire();
if (i % 3 == 0 && i % 5 == 0) {
fbSema.release();
} else if (i % 3 == 0) {
fSema.release();
} else if (i % 5 == 0) {
bSema.release();
} else {
printNumber.accept(i);
nSema.release();
}
}
}
}
class FizzBuzz {
private:
std::mutex mtx;
atomic<int> index;
int n;
// 这里主要运用到了C++11中的RAII锁(lock_guard)的知识。
// 需要强调的一点是,在进入循环后,要时刻不忘加入index <= n的逻辑
public:
FizzBuzz(int n) {
this->n = n;
index = 1;
}
void fizz(function<void()> printFizz) {
while (index <= n) {
std::lock_guard<std::mutex> lk(mtx);
if (0 == index % 3 && 0 != index % 5 && index <= n) {
printFizz();
index++;
}
}
}
void buzz(function<void()> printBuzz) {
while (index <= n) {
std::lock_guard<std::mutex> lk(mtx);
if (0 == index % 5 && 0 != index % 3 && index <= n) {
printBuzz();
index++;
}
}
}
void fizzbuzz(function<void()> printFizzBuzz) {
while (index <= n) {
std::lock_guard<std::mutex> lk(mtx);
if (0 == index % 15 && index <= n) {
printFizzBuzz();
index++;
}
}
}
void number(function<void(int)> printNumber) {
while (index <= n) {
std::lock_guard<std::mutex> lk(mtx);
if (0 != index % 3 && 0 != index % 5 && index <= n) {
printNumber(index);
index++;
}
}
}
};