2016-09-11 1 views
0

Мне нужно зарегистрировать заказ каждого клиента Официант может отправлять только заказы после записи всех запросов ваших клиентов. Клиента должен ждать, пока запрос не будет доставленКак синхронизировать потоки в java

Я не могу синхронизировать клиентские действия с официантом

мне нужно синхронизировать каждое действие от моих объектов Заказчика и официанта Заказчика имеет 1 заказ официант N клиенты

последовательность действий для синхронизации был реализован в «перспективе» метод каждого потока

package room; 

import java.util.Random; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class Customer extends Thread { 

    private Random random; 
    private int id; 
    private static int ID; 
    private Order order; 
    private Waiter waiter; 

    public Customer(Waiter garcom) { 
     this.random = new Random(); 
     this.id = ID + 1; 
     Customer.ID++; 
     this.waiter = garcom; 
    } 

    @Override 
    public void run() { 
     orderRequest(); 
     waitOrder(); 
     receiveRequest(); 
     consumer(); 
    } 

    public synchronized void orderRequest() { 
     synchronized (this.order) { 

      int r = random.nextInt(3); 
      switch (r) { 
       case 0: 
        this.order.setOrder("Food"); 
        break; 
       case 1: 
        this.order.setOrder("Drink"); 
        break; 
       default: 
        this.order.setOrder("Help"); 
        break; 
      } 

      System.out.println(this.toString() + " request " + this.order.getOrder() + "to " + this.waiter.toString()); 

       this.order.notify(); 

      try { 
       this.order.wait(); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Customer.class.getName()).log(Level.SEVERE, null, ex); 
      } 

     } 
    } 

    public synchronized void receiveRequest() { 

     synchronized (this.order) { 

      this.order.notify(); 

      try { 
       this.order.wait(); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Customer.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      System.out.println(this + " has received " + this.order + " from " + this.waiter); 
     } 
    } 

    private void waitOrder() { 
     synchronized (this.order) { 

      System.out.println(this + " consumer " + this.order); 

      this.order.notify(); 

      try { 
       this.order.wait(); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Customer.class.getName()).log(Level.SEVERE, null, ex); 
      } 

     } 
    } 

    public synchronized void consumer() { 

     synchronized (this.order) { 

      System.out.println(this + " was consumed " + this.order); 

      this.order.notify(); 

      try { 
       this.order.wait(); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Customer.class.getName()).log(Level.SEVERE, null, ex); 
      } 

     } 
    } 

    public void setOrder(Order order) { 
     this.order = order; 
    } 

    public Order getOrder() { 
     return order; 
    } 

    @Override 
    public String toString() { 
     return "Customer: " + id; 
    } 
} 

package room; 

public class Order { 

    private int orderNumber; 
    private static int ORDER_NUMBER = 0; 
    private Customer customer; 
    private String order; 

    public Order(Customer c) { 
     this.customer = c; 
     this.orderNumber = ORDER_NUMBER + 1; 
     this.customer.setOrder(this); 
     Order.ORDER_NUMBER++; 

    } 

    public String getOrder() { 
     return order; 
    } 

    public int getOrderNumber() { 
     return orderNumber; 
    } 


    public void setOrder(String order) { 
     this.order = order; 
    } 

    public Customer getCustomer() { 
     return customer; 
    } 

    @Override 
    public String toString() { 
     return "Order: " + order + " Nº " + orderNumber; 
    } 

} 

package room; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class Waiter extends Thread { 

    private Saloon saloon; 
    private int id; 
    private static int ID = 0; 
    private List<Order> orders; 

    public Waiter(Saloon bar) { 
     this.saloon = bar; 
     this.id = ID + 1; 
     Waiter.ID++; 
     this.orders = new ArrayList<>(); 

    } 

    @Override 
    public void run() { 

     while (saloon.isOpen()) { 

      registerOrder(); 
      deliveryRequest(); 

      saloon.round(); 
     } 
    } 

    public synchronized void registerOrder() { 

     for (Order order : orders) { 

      synchronized (order) { 

       order.notify(); 

       try { 
        order.wait(); 
       } catch (InterruptedException e) { 
        System.out.println(e.getMessage()); 
       } 
       System.out.println(this.toString() + " " 
         + "record " + order.toString() 
         + " to " + order.getCustomer()); 

      } 
     } 

    } 

    public synchronized void deliveryRequest() { 

     for (Order order : orders) { 

      synchronized (order) { 

       order.notify(); 

       try { 
        order.wait(); 
       } catch (InterruptedException ex) { 
        Logger.getLogger(Waiter.class.getName()).log(Level.SEVERE, null, ex); 
       } 

       System.out.println(this.toString() + " " 
         + "delivered " + order.toString() 
         + " to " + order.getCustomer()); 

      } 
     } 
    } 

    public synchronized void recordOrder(Order order) { 

     synchronized (orders) { 
      this.orders.add(order); 
     } 
    } 

    public List<Order> getOrders() { 
     return orders; 
    } 

    public Saloon getSaloon() { 
     return saloon; 
    } 

    @Override 
    public String toString() { 
     return "Waiter: " + id; 
    } 
} 

package room; 

import java.util.ArrayList; 
import java.util.List; 

public class Saloon { 

    private int maxRound; 
    private int numGarcons; 
    private volatile int round; 
    private int capacity; 
    private int customerCount; 
    private final List<Waiter> waiters; 

    public Saloon() { 
     this.waiters = new ArrayList<>(); 
     this.round = 1; 
    } 

    public Saloon(int customerCount, int waiterCount, 
      int capacity, int rounds) { 
     this(); 

     this.numGarcons = waiterCount; 
     this.customerCount = customerCount; 
     this.capacity = capacity; 
     this.maxRound = rounds; 

    } 

    /** 
    * Should it be call each round 
    */ 
    public void openBar() { 

     this.capacity = this.customerCount/this.capacity; 
     System.out.println("Round " + this.round); 

     for (int i = 0; i < this.numGarcons; i++) { 

      //Create a waiter 
      Waiter g = new Waiter(this); 

      for (int j = 0; j < this.capacity; j++) { 
       //create customer 
       Customer c = new Customer(g); 
       //an order 
       Order p = new Order(c); 
       //register order 
       g.recordOrder(p); 
       //call thread client 
       c.start(); 
      } 
      //waiter serves one client at a time 
      g.start(); 

      this.waiters.add(g); 
     } 

    } 

    public boolean isOpen() { 

     if (this.round < this.maxRound) { 
      return true; 
     } 
     return false; 
    } 

    public void round() { 
     this.round++; 
    } 
} 
+0

Так что для начала это выглядит как заказ никогда не устанавливаются для официанта. Вы создали заказ для клиента и задали его в списке заказов, но когда вы передаете это официанту? – Maxs728

+0

Просто так вы знаете, что я просматриваю весь код, хотя и исправляю его. – Maxs728

+0

Это очень похоже на [The Sleeping Barber problem] (http://web.cecs.pdx.edu/~harry/Blitz/OSProject/p3 /SleepingBarberProblem.pdf), [wiki] (https://en.wikipedia.org/wiki/Sleeping_barber_problem). Аналогия заключается в том, что официант похож на парикмахера, а задача Заказчика изменена с «Стрижка на заказ пищи». Есть незначительные различия, но вы можете начать [здесь] (https://www.cs.helsinki.fi/u/kerola/rio/ohjeet/Java/semaphores/s06e-huhtamaki-merikanto-nevalainen/SleepingBarber.java). – vsnyc

ответ

0

Ладно, я должен сказать, что я наслаждался вызов ... Но я понял это. Я должен отметить, что я попытался создать оригинальные maxRounds, и хотя он работает, есть ошибка, когда один дополнительный клиент может пройти через очередь. ПРИМЕЧАНИЕ: Я не утверждаю, что это самый лучший способ сделать это ... и не обязательно самый элегантный, но он должен указывать на правильное направление.

Я предлагаю прочитать около BlockingQueues и классы продлить его.

Главный вызов в салон:

public static void main(String[] args) { 
    Saloon saloon = new Saloon(100, 4, 50); 
    saloon.openBar(); 
} 

седан класса:

package room; 

import java.util.ArrayList; 
import java.util.List; 

public class Saloon { 

    private volatile static int round; 
    private static int maxRound; 
    private int numWaiters; 
    private final List<Waiter> waiters; 
    private int customerMax; // current implementation doesn't need this but you could if you wanted 
    private volatile static boolean isOpen; 
    private OrderQueue<Order> orderQueue; // This is the creation of the queue 

    public Saloon() { 
     this.waiters = new ArrayList<>(); 
     Saloon.round = 1; 
    } 

    public Saloon(int customerMax, int numWaiters, int maxRounds) { 
     this(); 
     this.customerMax = customerMax; 
     this.numWaiters = numWaiters; 
     this.orderQueue = new OrderQueue<Order>(numWaiters); 
     Saloon.maxRound = maxRounds; 
    } 

    /** 
    * Should it be call each round 
    */ 
    public void openBar() { 
     System.out.println("Round " + round); 
     isOpen = true; 
     // Create all waiters at once outside the loop 
     for (int i = 0; i < this.numWaiters; i++) { 
      waiters.add(new Waiter(i + 1, orderQueue)); 
      waiters.get(i).start(); 
     } 
     int customersServed = 1; // Generating the id number here is a better choice IMO 
     while(isOpen) { 
      for (Waiter waiter : waiters) { 
       if (round >= maxRound) { 
        closeBar(); 
       } 
       if (waiter.isAvailable() && !waiter.isClockedOut()) { 
        // create customer 
        Customer customer = new Customer(customersServed++, waiter, orderQueue); 
        customer.start(); 
       } 
      } 
     } 
    } 

    /** 
    * A simple implementation to close the bar 
    */ 
    public void closeBar() { 
     isOpen = false; // ends the loop 
     int waitersFinished = 0; // used to check if all waiters stopped serving 
     while (waitersFinished < numWaiters) { 
      for (Waiter waiter : waiters) { 
       if (waiter.isAvailable()) { 
        synchronized (orderQueue) { 
         // if nothing is currently in the queue for the waiters 
         if (orderQueue.isEmpty()) { 
          orderQueue.done(); // close the queue 
          orderQueue.notify(); // notify the queue 
         } 
         waiter.clockOut(); // clockout the waiter could use better implementation 
         waitersFinished++; // increment waiters finished 
        } 
       } 
      } 
     } 
    } 

    public static boolean isOpen() { 
     return isOpen; 
    } 

    // I would not recommend using this... this is the source of the glitch 
    public synchronized static void round() { 
     if (round <= maxRound) { // only if reached maxRounds 
      System.out.println("Round " + round); 
      round++; 
     } 
    } 
} 

OrderQueue Класс:

package room; 

import java.util.concurrent.ArrayBlockingQueue; 

/** 
* 
* Note I did not create this.. tomasb did and I implemented it. 
* 
* @param <T> 
*/ 
public class OrderQueue<T> extends ArrayBlockingQueue<T> { 

    private static final long serialVersionUID = 1L; 
    private boolean done = false; 

    /** 
    * creates an order queue with a max capacity.. orders that can be concurrently handled 
    * @param capacity 
    */ 
    public OrderQueue(int capacity) { 
     super(capacity); 
    } 

    /** 
    * closes the while loop ending this orderqueue 
    */ 
    public void done() { 
     done = true; 
    } 

    public boolean isDone() { 
     return done; 
    } 

    /** 
    * May return null if producer ends the production after consumer has 
    * entered the element-await state. 
    */ 
    public T take() throws InterruptedException { 
     T el; 
     while ((el = super.poll()) == null && !done) { 
      synchronized (this) { 
       wait(); 
      } 
     } 

     return el; 
    } 
} 

заказа Класс:

package room; 

public class Order { 

    private int orderNumber; 
    private static int ORDER_NUMBER = 0; 
    private String order; 

    public Order(int orderNumber) { 
     this.orderNumber = ORDER_NUMBER + 1; 
     this.orderNumber = orderNumber; 
    } 

    public String getOrder() { 
     return order; 
    } 

    public int getOrderNumber() { 
     return orderNumber; 
    } 

    public void setOrder(String order) { 
     this.order = order; 
    } 

    @Override 
    public String toString() { 
     return "Order: " + order + " Nº " + orderNumber; 
    } 
} 

клиентов Класс:

package room; 

import java.util.Random; 

public class Customer extends Thread { 

    private int id; 
    private int orderNumber = 1; 
    private Order order; 
    private Waiter waiter; 
    private OrderQueue<Order> orderQueue; // This provides an esay way to pass objects 

    public Customer(int id, Waiter waiter, OrderQueue<Order> orderQueue) { 
     this.id = id; 
     this.waiter = waiter; 
     this.orderQueue = orderQueue; 
     waiter.addCustomer(this); 
     System.out.println("Customer: " + id + " sat at a table!"); 
    } 

    @Override 
    public void run() { 
     // Notice that wait has been removed. The orderQueue takes care of this. 
     orderRequest(); 
     receiveRequest(); 
     consumer(); 
     System.out.println("Customer: " + id + " has left satisfied!"); 
    } 

    public void orderRequest() { 
     // none of thie should be synchronized as it is local 
     order = new Order(orderNumber++); 

     Random random = new Random(); 
     int r = random.nextInt(3); 
     switch (r) { 
     case 0: 
      order.setOrder("Food"); 
      break; 
     case 1: 
      order.setOrder("Drink"); 
      break; 
     default: 
      order.setOrder("Help"); 
      break; 
     } 

     System.out.println(this.toString() + " request " + order.getOrder() + " to " + this.waiter.toString()); 

     // only the call to the orderqueue is synchronized 
     try { 
      synchronized (orderQueue) { 
       orderQueue.put(order); 
       orderQueue.notify(); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void receiveRequest() { 
     System.out.println(this + " has received " + this.order + " from " + this.waiter); 
    } 

    public void consumer() { 
     System.out.println(this + " was consumed " + this.order); 
    } 

    @Override 
    public String toString() { 
     return "Customer: " + id; 
    } 
} 

И, наконец, официант Класс:

package room; 

public class Waiter extends Thread { 

    private int id; 
    private Order custOrder; 
    private Customer customer; 
    private volatile boolean isAvailable; 
    private volatile boolean clockOut; 
    private OrderQueue<Order> orderQueue; // The queue again 

    public Waiter(int id, OrderQueue<Order> orderQueue) { 
     this.id = id; 
     this.orderQueue = orderQueue; 
     System.out.println("Waiter " + id + " is ready to serve!"); 
    } 

    @Override 
    public void run() { 
     isAvailable = true; 
     while (!orderQueue.isDone() && !clockOut) { 
      if (isAvailable) { // this waiter is ready for a task 
       registerOrder(); 
       isAvailable = false; 
       synchronized (orderQueue) { // Synchronize this to the queue to prevent worse glitches 
        Saloon.round(); 
       } 
       if (custOrder != null) { // error checking 
        System.out.println(this.toString() + " record " + custOrder.toString() + " to " + customer); 
        deliveryRequest(); 
       } else { 
        isAvailable = true; 
       } 
      } 
     } 
    } 

    public synchronized void registerOrder() { 
     try { 
      custOrder = orderQueue.take(); // this is how you pull the order 
     } catch (InterruptedException e1) { 
      System.out.println(true); 
     } 
    } 

    public synchronized void deliveryRequest() { 
     System.out.println(this.toString() + " " + "delivered " + custOrder.toString() + " to " + customer); 
     isAvailable = true; 
    } 

    public void addCustomer(Customer customer) { // a easy way to add customers to the waiter after creation 
     this.customer = customer; 
     isAvailable = false; 
    } 

    public Order getOrder() { 
     return custOrder; 
    } 

    @Override 
    public String toString() { 
     return "Waiter: " + id; 
    } 

    public boolean isAvailable() { 
     return isAvailable; 
    } 

    public void clockOut() { 
     clockOut = true; 
    } 

    public boolean isClockedOut() { 
     return clockOut; 
    } 
} 
+0

. Дорогая, сначала я хочу поблагодарить вас и сказать, что я уже знал об этом классе BlockingQueues, но для этой проблемы использование этого класса было ограничено. Я хочу сделать это без класса ArrayBlockingQueue – filipecampos

+0

Я должен сказать, что не синхронизирована, круглая печать.Он повторяет раунд без необходимости и печатает тот же самый раунд перед круглой отделкой. Другое дело, он генерирует тупик, когда я пробую этот новый седан (3, 1, 3); – filipecampos

+0

Не работает тоже => новый седан (1,1,3); – filipecampos

 Смежные вопросы

  • Нет связанных вопросов^_^