简体   繁体   English

两个列表之间的同步

[英]Synchronization between two lists

I have the following problem that uses java concurrency.我有以下使用 java 并发的问题。

There are 3 clients and the cooker in a restaurant.一家餐厅有 3 位客户和炊具。 All of them change information through 2 lists.它们都通过 2 个列表更改信息。 One list for placing the orders, and another list for placing the meals.一份用于下订单的清单,另一份用于下餐的清单。 The customer sends the order to the order list, and the cooker reads it.客户将订单发送到订单列表,炊具读取。 The cooker sends the prepared meal to the customer on the meals list.炊具将准备好的餐点发送给餐单上的客户。 I implemented the cooker and the customer as threads that deal with the 2 lists.我将炊具和客户实现为处理 2 个列表的线程。 The goal of this problem is to synchronize access to the lists.此问题的目标是同步对列表的访问。 Unfortunately, the sequence of wait() and notifyAll() between threads are not good, and I am not getting what is the problem.不幸的是,线程之间的wait()notifyAll()顺序不好,我没有得到什么问题。 My code is below.我的代码如下。 Can anyone point me what is wrong with the code?谁能指出我的代码有什么问题?

Edit编辑

The problem is that the client and the cooker hangs without consuming all meals, as we can see from the output.问题是客户端和炊具在没有吃完所有食物的情况下挂起,正如我们从 output 中看到的那样。

Tony:    Client orders.
Tony:    The meal is still not ready.
Cooker:  Cooking Fish soup for Tony
Cooker:  The cooker will serve the meal Fish soup for Tony
Cooker:  Waiting for orders to cook.

Restaurant.java餐厅.java

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

public class Restaurant
{
   public static void main(String[] args)
   {
      List<Order> orderQueue = new ArrayList<>();
      List<Dish> dishesQueue = new ArrayList<>();

      // Client 1
      String clientName1 = "Tony";
      List<Order> personalOrders = new ArrayList<>();
      personalOrders.add(new Order(clientName1, "Fish soup"));
      personalOrders.add(new Order(clientName1, "Duck rice"));
      personalOrders.add(new Order(clientName1, "Coffee"));
      personalOrders.add(new Order(clientName1, "Pudding"));
      Thread tclient1 = new Thread(new Client(personalOrders, orderQueue, dishesQueue), clientName1);

      // Client 2
      String clientName2 = "John";
      personalOrders = new ArrayList<>();
      personalOrders.add(new Order(clientName2, "Stew"));
      personalOrders.add(new Order(clientName2, "Cake"));

      Thread tclient2 = new Thread(new Client(personalOrders, orderQueue, dishesQueue), clientName2);

      // Client 3
      String clientName3 = "Mike";
      personalOrders = new ArrayList<>();
      personalOrders.add(new Order(clientName3, "Hotdog"));
      personalOrders.add(new Order(clientName3, "Coffee"));
      Thread tclient3 = new Thread(new Client(personalOrders, orderQueue, dishesQueue), clientName3);

      Thread tCooker = new Thread(new Chef(orderQueue, dishesQueue), "Cooker");
      tclient1.start();
      tclient2.start();
      tclient3.start();

      tCooker.start();
   }
}

Chef.java厨师java

import java.util.List;

class Chef implements Runnable
{
   private final List<Order> orders;
   private final List<Dish> dishes;

   public Chef(List<Order> sharedOrders, List<Dish> sharedDishes)
   {
      this.orders = sharedOrders;
      this.dishes = sharedDishes;
   }

   @Override
   public void run()
   {
      while (true)
      {
         try
         {
            Order order = cook();
            serve(order);
         }
         catch (InterruptedException ex)
         {
            ex.printStackTrace();
         }
      }
   }

   private Order cook() throws InterruptedException {
      Order order = null;
      synchronized (orders) {
         if (orders.isEmpty()) {
            System.out.println(Thread.currentThread().getName() + ":\t Waiting for orders to cook.");
            Thread.sleep(1000);
            orders.wait();
         } else {
            order = orders.remove(0);
            System.out.println(Thread.currentThread().getName() + ":\t Cooking " + order.getDish() + " for " + order.getClientName());
            orders.notifyAll();
         }
      }
      return order;
   }

   private void serve(Order order) throws InterruptedException
   {
      synchronized (dishes)
      {
         if (dishes.isEmpty()) {
            System.out.println(Thread.currentThread().getName() + ":\t The cooker is waiting for more requests");
            dishes.wait();
         }

//         else {
         Thread.sleep(1000);
         Dish meal = new Dish(order.getClientName(), order.getDish());
         System.out.println(Thread.currentThread().getName() + ":\t The cooker will serve the meal " + meal.getDish() + " for " + meal.getClientName());
         dishes.add(meal);
         dishes.notifyAll();
//         }
      }
   }
}

Client.java客户端.java


import java.util.Collections;
import java.util.List;

class Client implements Runnable
{
   private final List<Order> orders;
   private final List<Order> personalOrders;
   private final List<Dish> dishes;

   public Client(List<Order> personalOrders, List<Order> orders, List<Dish> dishes)
   {
      this.personalOrders = personalOrders;
      this.orders = orders;
      this.dishes = dishes;
   }

   @Override
   public void run()
   {
      while (!personalOrders.isEmpty())
      {
         try
         {
            request(getPersonalOrders().remove(0));
            consume();
         } catch (InterruptedException ex)
         {
            ex.printStackTrace();
         }
      }
      System.out.println(Thread.currentThread().getName() + ":\t Acabou de comer.");
   }

   private void request(Order order) throws InterruptedException {
      synchronized (orders) {
         System.out.println(Thread.currentThread().getName() + ":\t Cliente faz pedido");
         orders.add(order);
         Thread.sleep(1000);
         orders.notifyAll();
      }
   }

   private void consume() throws InterruptedException
   {
      synchronized (dishes)
      {
         if (dishes.isEmpty())
         {
            System.out.println(Thread.currentThread().getName() + ":\t The meal is still not ready.");
            dishes.wait();
         }
//         else {
         Thread.sleep(1000);
         Dish meal = dishes.remove(0);
         System.out.println(Thread.currentThread().getName() + ":\t " + meal.getClientName() + " ready to eat " + meal.getDish());
         dishes.notifyAll();
//         }
      }
   }

   public List<Order> getPersonalOrders() {
      return personalOrders;
   }
}


This statement:这个说法:

this.dishes = Collections.synchronizedList(dishes);

makes this.dishes a different object than dishes .使this.dishes与 discs 不同dishes synchronize and notify on one of those objects won't affect the other object.在其中一个对象上同步和通知不会影响另一个 object。

That's why your clients are never notified about dishes ready.这就是为什么您的客户永远不会收到关于准备好的菜肴的通知。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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