🌕 🌗 1115. 交替打印 FooBar
2022年6月20日
- algorithm
🌕 🌗 1115. 交替打印 FooBar
难度: 🌕 🌗
问题描述
解法 1 - CyclicBarrier + flag
class FooBar {
// 思路: CyclicBarrier 循环栅栏
private int n;
CyclicBarrier c;
private int flag; // 标志位
public FooBar(int n) {
this.n = n;
this.c = new CyclicBarrier(2);
this.flag = 1;
}
public void foo(Runnable printFoo) throws InterruptedException {
for (int i = 0; i < n; i++) {
while(flag != 1) {
}
printFoo.run();
flag = 2;
try {
c.await(); // 执行 await() 会使容量 --
} catch (BrokenBarrierException e) {}
}
}
public void bar(Runnable printBar) throws InterruptedException {
for (int i = 0; i < n; i++) {
while(flag != 2) {
}
flag = 1;
printBar.run();
try {
c.await();
} catch (BrokenBarrierException e) {}
}
}
}
输出 1
解法 2 - ReentrantLock + Condition + flag
class FooBar {
// 思路:
// ReentrantLock + Condition
private int n;
ReentrantLock lock;
Condition c;
private int flag;
public FooBar(int n) {
this.n = n;
this.lock = new ReentrantLock();
this.c = lock.newCondition();
this.flag = 1;
}
public void foo(Runnable printFoo) throws InterruptedException {
for (int i = 0; i < n; i++) {
lock.lock();
try {
while(flag != 1) {
c.await(); // 进入 c 等待队列
}
printFoo.run();
flag = 2;
c.signal(); // 唤醒 c 等待队列
} finally {
lock.unlock();
}
}
}
public void bar(Runnable printBar) throws InterruptedException {
for (int i = 0; i < n; i++) {
lock.lock();
try {
while(flag != 2) {
c.await();
}
printBar.run();
flag = 1;
c.signal();
} finally {
lock.unlock();
}
}
}
}
解法 3 - Semaphore
class FooBar {
// 思路:
// 2 个 Semaphore 分别控制
private int n;
Semaphore s1;
Semaphore s2;
public FooBar(int n) {
this.n = n;
this.s1 = new Semaphore(1);
this.s2 = new Semaphore(0);
}
public void foo(Runnable printFoo) throws InterruptedException {
for (int i = 0; i < n; i++) {
s1.acquire();
printFoo.run();
s2.release();
}
}
public void bar(Runnable printBar) throws InterruptedException {
for (int i = 0; i < n; i++) {
s2.acquire();
printBar.run();
s1.release();
}
}
}
解法 4 - LinkedBlockingQueue
class FooBar {
// 思路:
// 2 个 LinkedBlockingQueue 分别控制,用 SynchronousQueue 却超时,疑问
private int n;
BlockingQueue<Integer> queue1;
BlockingQueue<Integer> queue2;
public FooBar(int n) {
this.n = n;
this.queue1 = new LinkedBlockingQueue<>(1);
try {
queue1.put(1);
} catch (Exception e) {}
this.queue2 = new LinkedBlockingQueue<>(1);
}
public void foo(Runnable printFoo) throws InterruptedException {
for (int i = 0; i < n; i++) {
queue1.take();
printFoo.run();
queue2.put(1);
}
}
public void bar(Runnable printBar) throws InterruptedException {
for (int i = 0; i < n; i++) {
queue2.take();
printBar.run();
queue1.put(1);
}
}
}