简体   繁体   中英

Multithreading in Java

I'm newbie in programming so I decided to write a simple multithreading program. It shows the work of the restaurant.Client orders food,waiter serves and cook prepares it. But I've got a problem, I think this is the case of deadlocking because when I run it, it prints "ordering" and nothing else. I can't understand what is wrong. Please help.Thanks.

Restaurant.java

public class Restaurant implements Runnable{
 Client cl=new Client();
 Chef ch=new Chef();
 Waiter w=new Waiter();

public synchronized void makeOrder() throws InterruptedException{
notifyAll();
cl.makeOrder();
wait();

}   

public synchronized void makeServing() throws InterruptedException{

notifyAll();
wait();

}

public synchronized void makeFood() throws InterruptedException{
notifyAll();
ch.makeFood();
Thread.sleep(1000);
wait();
}

@Override
public void run() {
    try {
    for(int i=0;i<10;i++){
        makeOrder();
        makeServing();
        makeFood();
    }
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

}

Client.java

public class Client{
public void makeOrder(){
System.out.println("Ordering"+Thread.currentThread().getId());
}

Waiter.java

public class Waiter {

public void makeServe() {
    System.out.println("Serving order"+Thread.currentThread().getId());

}

Chef.java

public class Chef {

public void makeFood(){

    System.out.println("Making food "+Thread.currentThread().getId());

}

Main.java

public class Main {
public static void main(String[] args) {

    Restaurant r=new Restaurant();
    Thread t=new Thread(r);
    t.start();
}

}

When you call makeOrder(); in the Restaurant thread it will wait(). And then nothing will happen anymore. The problem is, that you have only one thread, this one cannot notify itself. I think what you want to do is turn your Client, Waiter and Chef into threads. Then start them one after another and then the Waiter has to wait until the Client made his order and the Chef has to wait until the Waiter got the order...

You might find some helpful examples if you google for "java producer consumer example".

If you want to learn multithreading by modelling a restaurant, then try this model;

  1. Have a Restaurant class. Note that a restaurant is not Runnable because a restaurant itself it doesn't do anything (the people inside it do). The restaurant instead contains the other classes that actually 'do stuff'.

  2. Have a Waiter class. A waiter should periodically (eg every 1 minute) check the restaurant for customers waiting to order. If it finds a customer who wants to order it creates an order and adds it to a order queue. Your restaurant can contain several Waiter instances.

  3. Have a Chef class. The chef subscribes to the order queue that the waiters write to. Whenever a new order is created the chef cooks the order (this should take some time, eg 2 minutes) and then alerts any free waiter. The waiter then serves the food to the customer. Your restaurant can container several Chef instances.

  4. Have a Customer class. Customers should visit the restaurant at random intervals. They wait for a waiter to take their order, wait for the food to arrive, eat the food then leave. For bonus points give your restaurant a capacity and turn customers away/make them wait when it is full.

Concepts used in this example

  • Multithreading - Your restaurant will have many threads, each person (waiter, customer and chef) will run in their own thread.
  • Synchronisation - You need to synchronise between different threads (make sure two waiters don't serve a customer at the same time.
  • Producer/Consumer problem - The order queue is an example of a producer/consumer problem.
  • Resource starvation - Chefs can cook food but there may be no available waiters to serve it to the customer.
  • Deadlock - If you give your order queue a maximum size then you may encounter a deadlock if the queue gets full. You waiters are waiting to add to the queue and your chefs are waiting for free waiters to serve food.

You are misusing the wait/notify mechanism. :-) That's the real problem.

In Java, wait/notify is used to implement condition variables , which allows a thread to wait for a "condition" to be fulfilled. Another thread can also notify any waiting threads that said condition "may" be fulfilled, and to recheck the condition.

Here's a simple example:

public class Exchanger<T> {
    private T item;

    public synchronized T poll() {
        while (item == null)
            wait();
        T result = item;
        item = null;
        notifyAll();
        return result;
    }

    public synchronized void offer(T value) {
        if (value == null)
            throw new NullPointerException();
        while (item != null)
            wait();
        item = value;
        notifyAll();
    }
}

There are two conditions here (wrapped up under one condition variable, which normally isn't very kosher, but):

  • The item slot is null
  • The item slot isn't null

Basically, whenever poll or offer is called, it blocks until another thread does an offer or poll , respectively. To test for when to block, it does the relevant checks within the while loop.

Your code works (gives output) if you are using a main method that looks like this:

public static void main(String[] args) {
    Restaurant r = new Restaurant();
    new Thread(r).start();
    new Thread(r).start();
    new Thread(r).start();
}

The program will run for a while, and will then halt since it will wait for more "requests", it's not stuck in a deadlock. A deadlock requires two different locks, and you only got one in your code.

Note that you still might have logical "flaws/bugs"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM