public class ManufactureConsume {
public static void main(String[] args) {
CommodityStack cs = new CommodityStack();
Manufacture m = new Manufacture(cs);
Consumer c = new Consumer(cs);
//new Thread(m).start();
new Thread(m).start();
new Thread(m).start();
new Thread(c).start();
}
}
class Commodity {
public int id = 0;
Commodity (int id) {
this.id = id;
}
public String toString() {
return "Commodity:" + id;
}
}
class CommodityStack {
static int index = 0;
static Commodity[] c = new Commodity[6];
public synchronized void push (Commodity cd) {
while (index == c.length) {
try{
this.wait();
}catch (InterruptedException e) {}
}
this.notifyAll();
c[index] = cd;
index++;
}
public synchronized Commodity pop () {
while (index == 0) {
try{
this.wait();
}catch (InterruptedException e) {}
}
this.notifyAll();
index--;
return c[index];
}
}
class Manufacture implements Runnable {
CommodityStack cs = null;
Manufacture (CommodityStack cs) {
this.cs = cs;
}
public void run() {
for (int i = 0; i < 10; i++) {
Commodity cd = new Commodity(cs.index);
cs.push(cd);
System.out.println("制造" + cd);
try {
Thread.sleep(300);
} catch (InterruptedException e ) {}
}
}
}
class Consumer implements Runnable {
CommodityStack cs = null;
Consumer (CommodityStack cs) {
this.cs = cs;
}
public void run() {
while (cs.index != 0) {
System.out.println("吃掉了" + cs.pop());
try {
Thread.sleep(200);
} catch (InterruptedException e ) {}
}
}
}
问题是,在实际运行中,会出现同生产了两个同样ID的Commodity。也会出现同时消费了两个相同ID的Commodity的问题。也就是说,会出现一下的输出:
“
制造Commodity:3
制造Commodity:3
制造Commodity:4
吃掉了Commodity:4
制造Commodity:4
吃掉了Commodity:4
吃掉了Commodity:3
吃掉了Commodity:3
”这种情况是不是意味着生产和消费进程未能被独占锁定。有什么方法可以解决呢?
import static net.mindview.util.Print.*;
class Meal {
private final int orderNum;
public Meal(int orderNum) { this.orderNum = orderNum; }
public String toString() { return "Meal " + orderNum; }
}
class WaitPerson implements Runnable {
private Restaurant restaurant;
public WaitPerson(Restaurant r) { restaurant = r; }
public void run() {
try {
while(!Thread.interrupted()) {
synchronized(this) {
while(restaurant.meal == null)
wait(); // ... for the chef to produce a meal
}
print("Waitperson got " + restaurant.meal);
synchronized(restaurant.chef) {
restaurant.meal = null;
restaurant.chef.notifyAll(); // Ready for another
}
}
} catch(InterruptedException e) {
print("WaitPerson interrupted");
}
}
}
class Chef implements Runnable {
private Restaurant restaurant;
private int count = 0;
public Chef(Restaurant r) { restaurant = r; }
public void run() {
try {
while(!Thread.interrupted()) {
synchronized(this) {
while(restaurant.meal != null)
wait(); // ... for the meal to be taken
}
if(++count == 10) {
print("Out of food, closing");
restaurant.exec.shutdownNow();
}
printnb("Order up! ");
synchronized(restaurant.waitPerson) {
restaurant.meal = new Meal(count);
restaurant.waitPerson.notifyAll();
}
TimeUnit.MILLISECONDS.sleep(100);
}
} catch(InterruptedException e) {
print("Chef interrupted");
}
}
}
public class Restaurant {
Meal meal;
ExecutorService exec = Executors.newCachedThreadPool();
WaitPerson waitPerson = new WaitPerson(this);
Chef chef = new Chef(this);
public Restaurant() {
exec.execute(chef);
exec.execute(waitPerson);
}
public static void main(String[] args) {
new Restaurant();
}
}