【问题标题】:Thread synchronizing, using notifyAll()线程同步,使用 notifyAll()
【发布时间】:2015-05-11 20:04:34
【问题描述】:

这是 Bruce Eckel 的 Thinking in JAVA 3rd Edition,Revision 4.0,第 13 章(练习 10)中的练习。我应该有一个像厨师一样下订单并通知服务员的班级,以及两个等待订单准备好的服务员,然后接受它。

这是我目前所拥有的:

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 到达他应该等待()的部分,直到他得到通知。然后我得到一个IllegalMonitorStateException,这意味着线程正在等待对象的监视器而不拥有指定的监视器。不过还是想不通。

【问题讨论】:

    标签: java multithreading synchronized


    【解决方案1】:

    您的问题是您已在 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);
                    }
                }
    

    【讨论】:

    • 感谢您的评论!我应该使用 Restaurant.waitpersonsList.wait();
    【解决方案2】:

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

    如果您在 Restaurant.waitpersonsList 上进行同步,那么您也需要等待它,而引发异常的 wait() 正在尝试等待 WaiterList 对象本身。

    【讨论】:

    • 感谢您的评论!我现在明白了。
    猜你喜欢
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多