线程同步,使用 notifyAll()

Thread synchronizing, using notifyAll()

这是 Bruce Eckel 的 JAVA 第 3 版修订版 4.0 中第 13 章(练习 10)中的一个练习。我应该有一个 class 像厨师一样发出订单并通知服务员,还有两个服务员等待订单准备好,然后接受它。

这是我目前的情况:

class Order {
    private static int i = 0;
    private int count = i++;
    public Order() {
        if(count == 10) {
            System.out.println("Out of food, closing.");
            System.exit(0);
        }
    }
    public String toString() {
            return "Order " + count;
    }
}
class WaitPerson extends Thread {
    public  Restaurant restaurant;
    private int waitPersonId;
    public WaitPerson(Restaurant r, int waitPersonId) {
        restaurant = r;
        this.waitPersonId = waitPersonId;
        start();
    }
    public void run() {
        Order currentOrder;
        while(true) {

            while(restaurant.order == null) {

                synchronized(Restaurant.waitpersonsList) {
                    try {
                        System.out.println("Waitperson" + this.waitPersonId + " is waiting...");
                        wait();
                        System.out.println("WaitPerson" + this.waitPersonId + " is attempting to get " + restaurant.order);
                    }
                    catch(InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

            currentOrder = restaurant.order;
            System.out.println("Waitperson" + this.waitPersonId + " got " + currentOrder);
            restaurant.order = null;

            try {
                sleep(3000); //waitperson is busy for 3 seconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("Waitperson" + this.waitPersonId + " delivered " + currentOrder);

        }
    }
}
class Chef extends Thread {
    private Restaurant restaurant;
    private int ChefId;
    public Chef(Restaurant r, int ChefId) {
        restaurant = r;
        this.ChefId = ChefId;
        start();
    }
    public void run() {
        while(true) {
            if(restaurant.order == null) {
                restaurant.order = new Order();
                System.out.println("Chef" + this.ChefId + ": Order up! ");
                synchronized(Restaurant.waitpersonsList) {
                    Restaurant.waitpersonsList.notifyAll();
                }
            }
            try {
                sleep(100);
            }
            catch(InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

class Restaurant {
    public Order order;
    public static List<WaitPerson> waitpersonsList = Collections.synchronizedList(new ArrayList<WaitPerson>());
}
public class Main {
    public static void main(String[] args) {
        Restaurant r = new Restaurant();
        WaitPerson wp1 = new WaitPerson(r, 1);
        WaitPerson wp2 = new WaitPerson(r, 1);
        Restaurant.waitpersonsList.add(wp1);
        Restaurant.waitpersonsList.add(wp2);
        Chef chef = new Chef(r, 1);
    }
}

一切正常,直到 WaitPerson 到达他应该 wait() 的部分,直到他收到通知。然后我得到一个 IllegalMonitorStateException ,这意味着线程正在等待对象的监视器而不拥有指定的监视器。还是想不通。

您正在等待一个对象并通知另一个对象!

如果您在 Restaurant.waitpersonsList 上同步,那么您也需要等待它,而抛出异常的 wait() 试图等待 WaiterList 对象本身。

您的问题是您已经在 Restaurant.waitpersonsList 上进行了同步,但随后又在 WaitPerson 上调用了等待。您必须在

上调用 wait、notify 或 notifyAll 的任何对象上进行同步
             synchronized(Restaurant.waitpersonsList) {
                try {
                    System.out.println("Waitperson" + this.waitPersonId + " is waiting...");
                    wait();
                    System.out.println("WaitPerson" + this.waitPersonId + " is attempting to get " + restaurant.order);
                }
                catch(InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }