交替打印FooBar
我们提供一个类:
class FooBar {
public void foo() {
for (int i = 0; i < n; i++) {
print("foo");
}
}
public void bar() {
for (int i = 0; i < n; i++) {
print("bar");
}
}
}
两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。
请设计修改程序,以确保 “foobar” 被输出 n 次。
示例 1:
输入: n = 1
输出: “foobar”
解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,“foobar” 将被输出一次。
示例 2:
输入: n = 2
输出: “foobarfoobar”
解释: “foobar” 将被输出两次。
解题思路一
采用juc中的lock锁和Condition的方式实现
实现思路如下:
- 声明一个重入锁、一个变量、两个Condition(为了定向唤醒,不想声明两个、也可以声明一个、唤醒的时候采用SignalAll()方法)
- 题目中描述“foobar”的生成个数和n有关,所以,当"foo"生成之后,就要去唤醒生成“Bar”的方法
- 唤醒按照顺序指定,按照n的个数循环生成
具体代码如下:
/**************************************************************
* 描述:
* 交替打印FooBar
* @author zhusy 2020-07-07 16:42
*
**************************************************************/
public class FooBar {
private int n;
Lock lock = new ReentrantLock();
Condition conditionFirst = lock.newCondition();
Condition conditionSecond = lock.newCondition();
int num = 1;
public FooBar(int n) {
this.n = n;
}
public void foo(Runnable printFoo) throws InterruptedException {
lock.lock();
try {
for (int i = 0; i < n; i++) {
//为了防止虚假唤醒
while (num != 1){
conditionFirst.await();
}
num = 2;
// printFoo.run() outputs "foo". Do not change or remove this line.
printFoo.run();
conditionSecond.signal();
}
}finally {
lock.unlock();
}
}
public void bar(Runnable printBar) throws InterruptedException {
lock.lock();
try {
for (int i = 0; i < n; i++) {
//为了防止虚假唤醒
while (num != 2) {
conditionSecond.await();
}
num = 1;
// printBar.run() outputs "bar". Do not change or remove this line.
printBar.run();
conditionFirst.signal();
}
}finally {
lock.unlock();
}
}
}
解题思路二
采用Semaphore信号量的方式
解题思路如下:
- 声明两个信号量,在两个方法中交替等待、释放
- 防止第一次执行时两个方法都获取不到同时等待,所以先让先输出的方法执行
具体代码如下:
package leetcode;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**************************************************************
* 描述:
* 交替打印FooBar
* @author zhusy 2020-07-07 16:42
*
**************************************************************/
public class FooBar2 {
private int n;
public FooBar2(int n) {
this.n = n;
}
Semaphore semaphorebar = new Semaphore(0);
Semaphore semaphorefoo = new Semaphore(0);
public void foo(Runnable printFoo) throws InterruptedException {
for (int i = 0; i < n; i++) {
//防止第一次执行时获取不到
if (i != 0) {
semaphorefoo.acquire();
}
// printFoo.run() outputs "foo". Do not change or remove this line.
printFoo.run();
semaphorebar.release();
}
}
public void bar(Runnable printBar) throws InterruptedException {
for (int i = 0; i < n; i++) {
semaphorebar.acquire();
// printBar.run() outputs "bar". Do not change or remove this line.
printBar.run();
semaphorefoo.release();
}
}
}