题目:有一个盘子,盘子只能放一个水果,爸爸每次生产一个苹果,妈妈每次生产一个橘子,儿子每次消费一个苹果,女儿每次消费一个橘子,使用信号量实现;
分析:若使用synchronized实现,put时当容量不为1时必须轮训,若不轮训,无法保证盘子容量count为1;
public void putApple(Apple apple) {
synchronized (this) {
//这里必须轮训count,否则可能出现爸爸妈妈同时被唤醒然后同时加1使得count等于2,导致儿子女儿必须wait(),最后导致死锁
while (true) {
if (count != 0)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
else
break;
}
fruit = apple;
count++;
System.out.println("爸爸放了一个苹果: " + apple + "\t" + fruit.id + "\t" + count);
this.notifyAll();
}
}
其余几个方法类似
完整代码:
Plate类:
package proandconusesync;
public class Plate {
int count;
Fruit fruit;
public void putApple(Apple apple) {
synchronized (this) {
//这里必须轮训count,否则可能出现爸爸妈妈同时被唤醒然后同时加1使得count等于2,导致儿子女儿必须wait(),最后导致死锁
while (true) {
if (count != 0)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
else
break;
}
fruit = apple;
count++;
System.out.println("爸爸放了一个苹果: " + apple + "\t" + fruit.id + "\t" + count);
this.notifyAll();
}
}
public void putOrange(Orange orange) {
synchronized (this) {
while (true) {
if (count != 0)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
else
break;
}
fruit = orange;
count++;
System.out.println("妈妈放了一个橘子: " + orange + "\t" + orange.id + "\t" + count);
this.notifyAll();
}
}
public Apple getApple() {
synchronized (this) {
while (true) {
if (count != 1)
try {
this.wait();
} catch (InterruptedException e) {
}
else
break;
}
if (this.fruit instanceof Apple) {
count--;
Apple apple = (Apple) this.fruit;
this.fruit = null;
System.out.println("儿子吃了一个苹果: " + apple + "\t" + apple.id + "\t\t" + count);
this.notifyAll();
return apple;
} else
return null;
}
}
public Orange getOrange() {
synchronized (this) {
while (true) {
if (count != 1)
try {
this.wait();
} catch (InterruptedException e) {
}
else
break;
}
if (fruit instanceof Orange) {
count--;
Orange orange = (Orange) this.fruit;
this.fruit = null;
System.out.println("女儿吃了一个橘子: " + orange + "\t" + orange.id + "\t\t" + count);
this.notifyAll();
return orange;
} else
return null;
}
}
}
Main类:
package proandconusesync;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
public class Main2 {
public static Plate plate = new Plate();
public static AtomicInteger id = new AtomicInteger(0);
public static void main(String[] args) {
// 爸爸
new Thread(new Runnable() {
public Apple product() {
return new Apple(id.getAndIncrement());
}
public void run() {
while (true) {
Apple apple = product();
plate.putApple(apple);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
}).start();
// 媽媽
new Thread(new Runnable() {
public Orange product() {
return new Orange(id.getAndIncrement());
}
public void run() {
while (true) {
Orange orange = product();
plate.putOrange(orange);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
plate.getApple();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
plate.getOrange();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}