题目详细描述
解题思路主要在于信号量的使用!
话不多说,Foobar类,foo(),bar()方法,代码如下(注释超详细!)
本地IDEA执行(jdk1.8)
import java.util.concurrent.Semaphore;
/**
* 两个不同的线程将会共用一个FooBar实例
* 其中一个线程调用foo()方法,另一个线程调用bar()方法
* 确保"foobar"被输出n次
*/
public class FooBar {
private int n;
public FooBar(int n){
this.n = n;
}
//public Semaphore(int permits){sync = new NonfairSync(permits);}
// 新建信号量, permits值为 允许可用的初始许可数量,可以为负值,但是必须是有许可被赋予的情况下
private Semaphore sema_foo = new Semaphore(1); //sema_foo 初始许可为1
private Semaphore sema_bar = new Semaphore(0); //sema_bar 初始许可为0
public void foo(){
for(int i=1;i<=n;i++) {
try {
//请求获得许可,若存在许可,则获得的同时许可数量减一,若不存在则阻塞进入等待状态
sema_foo.acquire(); //1.初始许可为1,可以获得许可,代码继续执行
System.out.print("第"+i+"次交替:foo");
} catch (InterruptedException e) {
e.printStackTrace();
}
//释放许可,但必须在获得许可的前提下才能够释放,释放后许可数量加一
sema_bar.release(); //2.初始许可为0,释放许可必须要先获得许可,线程阻塞,进入步骤3
//2.1 因步骤3.1获得许可,此时可以释放,(第一次交替执行结束),从步骤1重新开始
}
}
public void bar(){
for(int i=1;i<=n;i++) {
try {
sema_bar.acquire(); //3.此时许可数为0,阻塞等待(异常),3.1获得释放的许可,代码继续执行
System.out.println("bar");
} catch (InterruptedException e) {
e.printStackTrace();
}
sema_foo.release(); //4.释放许可,重新进入步骤3.1 4.1此时释放许可,线程阻塞,进入步骤2.1(参照步骤2)
}
}
public static void main(String[] args) {
FooBar fooBar = new FooBar(3);
System.out.println("两个线程交替执行(输出如下):");
// new Thread(new Runnable(){
// @Override
// public void run(){
// fooBar.foo();
// }
// }).start();
// new Thread(new Runnable(){
// @Override
// public void run(){
// fooBar.bar();
// }
// }).start();
//Anonymous new Runnable() can be replaced with lambda
//Lambda syntax is not supported under Java 1.7 or earlier JVMs.
new Thread(()->fooBar.foo()).start();
new Thread(()->fooBar.bar()).start();
}
}
输出如下:
两个线程交替执行(输出如下):
第1次交替:foobar
第2次交替:foobar
第3次交替:foobar