5
\$\begingroup\$

I wrote program which simulates the work of the restaurant. It works but I would like to change it because I think there is better solution.Thanks for your suggestions.

Client.java

public class Client implements Runnable {
    private Restaurant r;

    public void makeOrder() throws InterruptedException {
        synchronized (r) {
            r.notifyAll();
            System.out.println("Start ordering ");
            Thread.sleep(1000);
            r.putOrderMadeByClient(r.orderId);
            System.out.println("End ordering ");
            while(r.orderReceived==false)
                r.wait();
            r.getOrderReceived();
        }
    }

    public Client(Restaurant r) {
        this.r=r;
    }

    public void run() {
        try {
            makeOrder();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Waiter.java

public class Waiter implements Runnable {
    private Restaurant r;

    public void makeServe() throws InterruptedException {
        synchronized (r) {
            r.notifyAll();
            while(r.orderMadeByClient==false)
                r.wait();
            System.out.println("Start serving order ");
            Thread.sleep(1000);
            r.putOrder(r.getOrderMadeByClient());
            while(r.orderReady==false)
                r.wait();
            r.putOrderReceived(r.getFood());   
            System.out.println("End serving order ");
        }
    }

    public Waiter(Restaurant r) {
        this.r=r;
    }

    @Override
    public void run() {
        try {
            makeServe();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Chef.java

public class Chef implements Runnable {
    private Restaurant r;

    public void makeFood() throws InterruptedException {
        synchronized (r) {
            r.notifyAll();
            while(r.orderTaken==false)
                r.wait();
            System.out.println("Start making food ");
            Thread.sleep(1000);
            r.putFood(r.getOrder());
            System.out.println("End making food ");
        }
    }

    public Chef(Restaurant r) {
        this.r=r;
    }

    @Override
    public void run() {
        try {
            makeFood();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Restaurant.java

public class Restaurant {
    boolean orderMadeByClient;
    boolean orderTaken;
    boolean orderReady;
    boolean orderReceived;
    long orderId;

    public Restaurant() {
    }

    public void makeRestaurant() {
        Client cl = new Client(this);
        Chef ch = new Chef(this);
        Waiter w = new Waiter(this);
        Thread t1 = new Thread(cl);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(ch);

        t1.start();
        t2.start();
        t3.start();
    }

    synchronized long getOrderMadeByClient() {
        while (!orderMadeByClient) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        orderMadeByClient = false;
        notifyAll();
        System.out.println("get order from client #" + orderId);
        return orderId;
    }

    synchronized void putOrderMadeByClient(long l) {
        while (orderMadeByClient) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        orderMadeByClient = true;
        this.orderId = l;
        notifyAll();
        System.out.println("put order client #" + l);
    }

    synchronized long getOrder() {
        while (!orderTaken) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        orderTaken = false;
        notifyAll();
        System.out.println("get order from waiter #" + orderId);
        return orderId;
    }

    synchronized void putOrder(long l) {
        while (orderTaken) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        orderTaken = true;
        this.orderId = l;
        notifyAll();
        System.out.println("put order to cook #" + l);
    }

    synchronized long getFood() {
        while (!orderReady) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        orderReady = false;
        notifyAll();
        System.out.println("get order by waiter #" + orderId);
        return orderId;
    }

    synchronized void putFood(long n) {
        while (orderReady) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        orderReady = true;
        this.orderId = n;
        notifyAll();
        System.out.println("put order by cook #" + n);
    }

    synchronized long getOrderReceived() {
        while (!orderReceived) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        orderReceived = false;
        notifyAll();
        System.out.println("get order by client #" + orderId);
        return orderId;
    }

    synchronized void putOrderReceived(long l) {
        while (orderReceived) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        orderReceived = true;
        this.orderId = l;
        notifyAll();
        System.out.println("put order by waiter #" + l);
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Restaurant r=new Restaurant();
        r.makeRestaurant();
    }
}
\$\endgroup\$
1
4
\$\begingroup\$

The main issue here is that everything synchronizes on the restaurant object. This means that the chef cannot prepare food while the client is placing an order, waiters cannot serve while the chef is cooking, etc. The first step would be to add BlockingQueues to Restaurant and let them manage all of the calls to wait() and notify() for you.

You'd need one queue of orders that waiters place and chefs take and another for food that chefs place and waiters take. When a Chef calls take() on the order queue, it will block until there is an order available. A Waiter calling offer() on the same queue will block until there is room in the queue. You can make the queues bounded (maximum size) or unbounded.

You might even create a queue to hold the clients waiting to place orders. Waiters would poll() the food and client queues in their run() loop so they don't wait forever for food to be ready when they haven't even placed any orders yet.

public void run() {
    while (true) {
        Food f = foodQueue.poll(2, TimeUnit.SECONDS);
        if (f != null) {
            // deliver food to client...
        }
        Order o = clientQueue.poll(2, TimeUnit.SECONDS);
        if (o != null) {
            if (!orderQueue.offer(o, 120, TimeUnit.SECONDS)) {
                // kitchen is too busy!
                break; // waiter quits out of frustration
            }
        }
    }
}

The Chef class currently waits for a second and then takes the order and makes the food available immediately. Instead, it should take the order, then wait, and finally make the food available. If you were to create a queue for the use of the chef while cooking, you could use a priority queue (orders the elements in the queue) and have different types of food take different lengths of time to prepare. The chef would then have multiple things cooking at once and deliver each after its own cook time has expired.

With the above in place you could really kick this into high gear by creating multiple waiters and chefs and add a separate thread that randomly creates clients that place random orders.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.