LeetCode 1195. 交替打印字符串
题目描述
思路分析
解法一:信号量协调(推荐)
核心思路:
- 由
number线程决定当前数字应由哪个线程输出。- 使用四个信号量分别控制
fizz、buzz、fizzbuzz与number。- 被唤醒的打印线程完成输出后释放
number,继续下一轮。
复杂度分析:
- 时间复杂度:O(n),其中 n 表示输出数字的范围上界。
- 空间复杂度:O(1),仅使用常数个同步原语。
import java.util.concurrent.Semaphore;
import java.util.function.IntConsumer;
class FizzBuzz {
private int n;
private final Semaphore number = new Semaphore(1);
private final Semaphore fizz = new Semaphore(0);
private final Semaphore buzz = new Semaphore(0);
private final Semaphore fizzbuzz = new Semaphore(0);
public FizzBuzz(int n) {
this.n = n;
}
public void fizz(Runnable printFizz) throws InterruptedException {
for (int i = 3; i <= n; i += 3) {
if (i % 5 == 0) {
continue;
}
fizz.acquire();
printFizz.run();
number.release();
}
}
public void buzz(Runnable printBuzz) throws InterruptedException {
for (int i = 5; i <= n; i += 5) {
if (i % 3 == 0) {
continue;
}
buzz.acquire();
printBuzz.run();
number.release();
}
}
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
for (int i = 15; i <= n; i += 15) {
fizzbuzz.acquire();
printFizzBuzz.run();
number.release();
}
}
public void number(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++) {
number.acquire();
if (i % 15 == 0) {
fizzbuzz.release();
} else if (i % 3 == 0) {
fizz.release();
} else if (i % 5 == 0) {
buzz.release();
} else {
printNumber.accept(i);
number.release();
}
}
}
}
type FizzBuzz struct {
n int
numberCh chan struct{}
fizzCh chan struct{}
buzzCh chan struct{}
fbCh chan struct{}
}
func Constructor(n int) FizzBuzz {
fb := FizzBuzz{
n: n,
numberCh: make(chan struct{}, 1),
fizzCh: make(chan struct{}, 1),
buzzCh: make(chan struct{}, 1),
fbCh: make(chan struct{}, 1),
}
fb.numberCh <- struct{}{}
return fb
}
func (fb *FizzBuzz) Fizz(printFizz func()) {
for i := 3; i <= fb.n; i += 3 {
if i%5 == 0 {
continue
}
<-fb.fizzCh
printFizz()
fb.numberCh <- struct{}{}
}
}
func (fb *FizzBuzz) Buzz(printBuzz func()) {
for i := 5; i <= fb.n; i += 5 {
if i%3 == 0 {
continue
}
<-fb.buzzCh
printBuzz()
fb.numberCh <- struct{}{}
}
}
func (fb *FizzBuzz) Fizzbuzz(printFizzBuzz func()) {
for i := 15; i <= fb.n; i += 15 {
<-fb.fbCh
printFizzBuzz()
fb.numberCh <- struct{}{}
}
}
func (fb *FizzBuzz) Number(printNumber func(int)) {
for i := 1; i <= fb.n; i++ {
<-fb.numberCh
if i%15 == 0 {
fb.fbCh <- struct{}{}
} else if i%3 == 0 {
fb.fizzCh <- struct{}{}
} else if i%5 == 0 {
fb.buzzCh <- struct{}{}
} else {
printNumber(i)
fb.numberCh <- struct{}{}
}
}
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 1114. 按序打印 | 简单 | 多线程 |
| 1115. 交替打印 FooBar | 中等 | 多线程 |
| 1116. 打印零与奇偶数 | 中等 | 多线程 |
| 1117. H2O 生成 | 中等 | 多线程 |
| 1226. 哲学家进餐 | 中等 | 多线程 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!