1114. 按序打印
我们提供了一个类:
public class Foo {
public void one() { print("one"); }
public void two() { print("two"); }
public void three() { print("three"); }
}
三个不同的线程将会共用一个 Foo 实例。
线程 A 将会调用 one() 方法
线程 B 将会调用 two() 方法
线程 C 将会调用 three() 方法
请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。
第一种方法 countdownlatch方法
class Foo {
private CountDownLatch c2=new CountDownLatch(1);
private CountDownLatch c3=new CountDownLatch(1);
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
c2.countDown();
}
public void second(Runnable printSecond) throws InterruptedException {
c2.await();
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
c3.countDown();
}
public void third(Runnable printThird) throws InterruptedException {
c3.await();
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
}
}
第二种方法 CAS
class Foo {
private AtomicInteger c2=new AtomicInteger(0);
private AtomicInteger c3=new AtomicInteger(0);
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException{
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
c2.incrementAndGet();
}
public void second(Runnable printSecond) throws InterruptedException {
// printSecond.run() outputs "second". Do not change or remove this line.
while (c2.get()!=1){}
printSecond.run();
c3.incrementAndGet();
}
public void third(Runnable printThird) throws InterruptedException {
// printThird.run() outputs "third". Do not change or remove this line.
while (c3.get()!=1){}
printThird.run();
}
}
第三种方法 信号量
class Foo {
private Semaphore c2=new Semaphore(0);
private Semaphore c3=new Semaphore(0);
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException{
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
c2.release();
}
public void second(Runnable printSecond) throws InterruptedException{
// printSecond.run() outputs "second". Do not change or remove this line.
c2.acquire();
printSecond.run();
c3.release();
}
public void third(Runnable printThird) throws InterruptedException {
// printThird.run() outputs "third". Do not change or remove this line.
c3.acquire();
printThird.run();
}
}
第四种方法 synchronized方法
class Foo {
private final Object o=new Object();
private int state=1;
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException{
// printFirst.run() outputs "first". Do not change or remove this line.
synchronized (o) {
printFirst.run();
state=2;
o.notifyAll();
}
}
public void second(Runnable printSecond) throws InterruptedException{
// printSecond.run() outputs "second". Do not change or remove this line.
synchronized (o) {
while (state!=2){
o.wait();
}
printSecond.run();
state=3;
o.notifyAll();
}
}
public void third(Runnable printThird) throws InterruptedException {
// printThird.run() outputs "third". Do not change or remove this line.
synchronized (o) {
while (state!=3){
o.wait();
}
printThird.run();
}
}
}
第五种方法 lock方法
class Foo {
private ReentrantLock lock=new ReentrantLock();
private Condition c2=lock.newCondition();
private Condition c3=lock.newCondition();
private int state=1;
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException{
// printFirst.run() outputs "first". Do not change or remove this line.
try {
lock.lock();
printFirst.run();
c2.signal();
state=2;
}finally {
lock.unlock();
}
}
public void second(Runnable printSecond) throws InterruptedException{
// printSecond.run() outputs "second". Do not change or remove this line.
try{
lock.lock();
while (state!=2){
c2.await();
}
printSecond.run();
state=3;
c3.signal();
}finally {
lock.unlock();
}
}
public void third(Runnable printThird) throws InterruptedException {
// printThird.run() outputs "third". Do not change or remove this line.
try{
lock.lock();
while (state!=3){
c3.await();
}
printThird.run();
}finally {
lock.unlock();
}
}
}
1115. 交替打印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 次。
class FooBar {
private int n;
private Object lock=new Object();
private int count=1;
public FooBar(int n) {
this.n = n;
}
public void foo(Runnable printFoo) throws InterruptedException {
for (int i = 0; i < n; i++) {
synchronized (lock) {
while (count!=1)lock.wait();
// printFoo.run() outputs "foo". Do not change or remove this line.
printFoo.run();
lock.notifyAll();
count--;
}
}
}
public void bar(Runnable printBar) throws InterruptedException {
for (int i = 0; i < n; i++) {
synchronized (lock) {
while (count!=0)lock.wait();
// printBar.run() outputs "bar". Do not change or remove this line.
printBar.run();
lock.notifyAll();
count++;
}
}
}
}
1116. 打印零与奇偶数
假设有这么一个类:
class ZeroEvenOdd {
public ZeroEvenOdd(int n) { ... } // 构造函数
public void zero(printNumber) { ... } // 仅打印出 0
public void even(printNumber) { ... } // 仅打印出 偶数
public void odd(printNumber) { ... } // 仅打印出 奇数
}
相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程:
线程 A 将调用 zero(),它只输出 0 。
线程 B 将调用 even(),它只输出偶数。
线程 C 将调用 odd(),它只输出奇数。
每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n。
class ZeroEvenOdd {
private int n;
private Semaphore zero=new Semaphore(1);
private Semaphore odd=new Semaphore(0);
private Semaphore even=new Semaphore(0);
public ZeroEvenOdd(int n) {
this.n = n;
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void zero(IntConsumer printNumber) throws InterruptedException {
for(int i=1;i<=n;i++){
zero.acquire();
printNumber.accept(0);
if((i&1)==1){
odd.release();
}else{
even.release();
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
for(int i=2;i<=n;i+=2){
even.acquire();
printNumber.accept(i);
zero.release();
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
for(int i=1;i<=n;i+=2) {
odd.release();
printNumber.accept(i);
zero.release();
}
}
}
1117. H2O 生成
每次获取一个H,需要释放一个O,O需要获取2个,同时H释放两个
class H2O {
private Semaphore h=new Semaphore(2);
private Semaphore o=new Semaphore(0);
public H2O() {
}
public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
// releaseHydrogen.run() outputs "H". Do not change or remove this line.
h.acquire();
releaseHydrogen.run();
o.release();
}
public void oxygen(Runnable releaseOxygen) throws InterruptedException {
// releaseOxygen.run() outputs "O". Do not change or remove this line.
o.acquire(2);
releaseOxygen.run();
h.release(2);
}
}
1195. 交替打印字符串
编写一个可以从 1 到 n 输出代表这个数字的字符串的程序,但是:
如果这个数字可以被 3 整除,输出 "fizz"。
如果这个数字可以被 5 整除,输出 "buzz"。
如果这个数字可以同时被 3 和 5 整除,输出 "fizzbuzz"。
class FizzBuzz {
private int n;
private ReentrantLock lock=new ReentrantLock();
private Condition f=lock.newCondition();
private Condition b=lock.newCondition();
private Condition fb=lock.newCondition();
private Condition nc=lock.newCondition();
private boolean state=false;
public FizzBuzz(int n) {
this.n = n;
}
// printFizz.run() outputs "fizz".
public void fizz(Runnable printFizz) throws InterruptedException {
for(int i=3;i<=n;i+=3){
lock.lock();
try {
if (i % 5 != 0) {
while (!state){
f.await();
}
printFizz.run();
state=false;
nc.signal();
}
}finally {
lock.unlock();
}
}
}
// printBuzz.run() outputs "buzz".
public void buzz(Runnable printBuzz) throws InterruptedException {
for(int i=5;i<=n;i+=5){
lock.lock();
try {
if(i%3!=0){
while (!state){
b.await();
}
printBuzz.run();
state=false;
nc.signal();
}
}finally {
lock.unlock();
}
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
for(int i=15;i<=n;i+=15){
lock.lock();
try {
while (!state){
fb.await();
}
printFizzBuzz.run();
state=false;
nc.signal();
}finally {
lock.unlock();
}
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void number(IntConsumer printNumber) throws InterruptedException {
for(int i=1;i<=n;i++){
lock.lock();
try {
while (state){
nc.await();
}
if(i%3==0&&i%5==0){
fb.signal();
state=true;
}
else if(i%3==0){
f.signal();
state=true;
}else if(i%5==0){
b.signal();
state=true;
}else {
printNumber.accept(i);
nc.signal();
}
}finally {
lock.unlock();
}
}
}
}
1226. 哲学家进餐
class DiningPhilosophers {
private ReentrantLock[] locks=new ReentrantLock[]{
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock()
};
private Semaphore eatLimit=new Semaphore(4);
public DiningPhilosophers() {
}
// call the run() method of any runnable to execute its code
public void wantsToEat(int philosopher,
Runnable pickLeftFork,
Runnable pickRightFork,
Runnable eat,
Runnable putLeftFork,
Runnable putRightFork) throws InterruptedException {
int left=(philosopher+1)%5;
int right=philosopher;
eatLimit.acquire();
locks[left].lock();
locks[right].lock();
pickLeftFork.run();
pickRightFork.run();
eat.run();
putLeftFork.run();
putRightFork.run();
locks[left].unlock();
locks[right].unlock();
eatLimit.release();
}
}