线程同步,使用notifyAll()

时间:2015-05-11 20:04:35

标签: java multithreading synchronized

这是Bruce Eckel在JAVA第3版,修订版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,这意味着线程正在等待对象的监视器而不拥有指定的监视器。但是,无法解决这个问题。

2 个答案:

答案 0 :(得分:2)

您正在等待一个物体并通知另一个物体!

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

答案 1 :(得分:2)

您的问题是您已经在Restaurant.waitpersonsList上进行了同步,但随后在WaitPerson上调用了wait。您必须在您调用wait,notify或notifyAll的任何对象上同步

ViewModel.DataLine