两个列表之间的同步
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两个列表之间的同步相关的知识,希望对你有一定的参考价值。
我有以下使用Java并发的问题。
[一家餐厅有3位客户和炊具。它们全部通过2个列表更改信息。一个用于下订单的列表,另一个用于下饭菜的列表。客户将订单发送到订单列表,电磁炉读取该订单。炊具将准备好的饭菜发送给饭菜清单上的客户。我将炊具和客户实现为处理这两个列表的线程。此问题的目的是同步对列表的访问。不幸的是,线程之间的wait()
和notifyAll()
顺序不好,并且我没有得到什么问题。我的代码如下。谁能指出我的代码有问题吗?
编辑
问题是客户和炊具挂起而没有消耗所有食物,正如我们从输出中看到的。
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
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
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
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.dishes = Collections.synchronizedList(dishes);
使this.dishes
与dishes
不同。在其中一个对象上进行同步和通知不会影响另一个对象。
这就是为什么您的客户永远不会收到有关准备好的菜肴的通知。
以上是关于两个列表之间的同步的主要内容,如果未能解决你的问题,请参考以下文章