题目:有一个盘子,盘子只能放一个水果,爸爸每次生产一个苹果,妈妈每次生产一个橘子,儿子每次消费一个苹果,女儿每次消费一个橘子,使用信号量实现;
分析:因为盘子是有容量的,一个信号量并不能保证盘子的容量是否超过一个(除非重复轮训盘子数量,put时若盘子数量不等于0则wait,直到盘子数量等于0打破轮训),这里通过使用两个信号量notEmpty,notFull分别表示盘子是否为空,是否已满来实现;
Plate类:
package proandconusesemaphore;
import java.util.concurrent.Semaphore;
import proandconusesync.Apple;
import proandconusesync.Fruit;
import proandconusesync.Orange;
public class Plate {
Semaphore notFull = new Semaphore(1);
Semaphore notEmpty = new Semaphore(0);
// Semaphore mutex = new Semaphore(1);
Fruit fruit;
public void putApple(Apple apple) {
try {
notFull.acquire();
this.fruit = apple;
System.out.println("爸爸放了一个苹果: " + apple + " " + apple.id);
notEmpty.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void putOrange(Orange orange) {
try {
notFull.acquire();
this.fruit = orange;
System.out.println("妈妈放了一个橘子: " + orange + " " + orange.id);
notEmpty.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Apple getApple() {
try {
notEmpty.acquire();
if (this.fruit instanceof Apple) {
Apple apple = (Apple) this.fruit;
System.out.println("儿子吃了一个苹果: " + apple + " " + apple.id);
this.fruit = null;
notFull.release();
return apple;
} else {
notEmpty.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public Orange getOrange() {
try {
notEmpty.acquire();
if (this.fruit instanceof Orange) {
Orange orange = (Orange) this.fruit;
this.fruit = null;
System.out.println("女儿吃了一个橘子: " + orange + " " + orange.id);
notFull.release();
return orange;
}else{
notEmpty.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
Main类:
package proandconusesemaphore;
import java.util.concurrent.atomic.AtomicInteger;
import proandconusesync.Apple;
import proandconusesync.Orange;
public class Main {
public static Plate plate = new Plate();
public static AtomicInteger id = new AtomicInteger(0);
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
while (true) {
Apple apple = new Apple(id.getAndIncrement());
plate.putApple(apple);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
Orange orange = new Orange(id.getAndIncrement());
plate.putOrange(orange);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
plate.getApple();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
plate.getOrange();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
}).start();
}
}