thinking in java 多线程 顾客、服务生、厨师的例子

cargoj 2012-03-13 09:11:19
多个顾客、多个服务生、多个厨师,服务生需要同时检查顾客点菜请求、厨师完成通知,如何处理?
...全文
433 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
cargoj 2012-03-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 iisgirl 的回复:]
引用 4 楼 cargoj 的回复:

在没有加入顾客的情况下,多个服务生、多个厨师由服务生自己下订单,在餐厅加入订餐LIST、准备就绪Map<Waiter,Order>后已经解决。


但是加入顾客以后,Waiter除了需要检查准备就绪Map以外还需要检查顾客订餐LIST,这该怎么处理呢?


订餐LIST 这个是顾客的行为啊,顾客就是一个线程。
[/Quote]

顾客、服务生、厨师都是一个线程。我的问题是服务生不知道怎么处理。
MiceRice 2012-03-14
  • 打赏
  • 举报
回复
用标准的资源争用其实就已经能解决问题了,实际上就是谁先抢到算谁的,那么在极低概率下顾客有可能被饿死。


不过也可以延伸下设计,考虑增加事件队列。
相当于顾客喊服务生,就相当于发出一条指令进入队列,那么空闲服务生从指令队列中接下一个任务。
cargoj 2012-03-14
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 ldh911 的回复:]
“一个顾客进店后会被指定一个服务生,然后每次订餐都会找这个服务生”

这个假设不符合实际情况。

应该是订餐时就找有空闲的服务生,如果没有空闲服务生,就必须等到某服务生有空闲。
[/Quote]

我是忽略了这个过程,因为我处理不了服务生同时等待厨师、顾客进点通知。
你能给点提示吗?
MiceRice 2012-03-14
  • 打赏
  • 举报
回复
“一个顾客进店后会被指定一个服务生,然后每次订餐都会找这个服务生”

这个假设不符合实际情况。

应该是订餐时就找有空闲的服务生,如果没有空闲服务生,就必须等到某服务生有空闲。
cargoj 2012-03-14
  • 打赏
  • 举报
回复

class Order {
private static int i = 0;
private int count = i++;
private WaitPerson waiter;
public Order(WaitPerson w) {
this.waiter = w;
if(count == 10){
System.out.println("Out of food, closing");
System.exit(0);
}
}
public WaitPerson getWaiter(){
return this.waiter;
}
public String toString() { return "Order" + count; }
}
class Custom extends Thread {
int num;
Restaurant restaurant;
WaitPerson waitPerson;
Custom(int num, Restaurant r, WaitPerson w){
this.num = num;
this.restaurant = r;
this.waitPerson = w;
start();

}
public void run(){
try {
while(true){
sleep(1000);
synchronized (restaurant.getOrderList()) {
Order order = new Order(this.waitPerson);
restaurant.newOrder(order);
restaurant.getOrderList().notifyAll();
System.out.println("No." + this.num + " custom order up " + order);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String toString() {return "";}
}
class WaitPerson extends Thread {
private Restaurant restaurant;
private String name;
public WaitPerson(String name, Restaurant r){
restaurant = r;
this.name = name;
start();
}
public void run(){
while(true){
try {
synchronized (restaurant.getReadyList()) {
while(restaurant.getReady(this) == null){
synchronized (this) {
this.wait();
}
}
Order removed = restaurant.removeReady(this);
System.out.println(this.name + " got " + removed);
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}

class Chef extends Thread{
private String name;
private Restaurant restaurant;
public Chef(String name,Restaurant r){
this.name = name;
restaurant = r;
start();
}
public void run(){
while(true){
synchronized (restaurant.getOrderList()) {
while(restaurant.getFirstOrder() == null){
try {
restaurant.getOrderList().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}//模拟做菜4秒
Order o = restaurant.getFirstOrder();
restaurant.newReady(o.getWaiter(), o);
System.out.println(this.name + " done order " + o);
synchronized (o.getWaiter()) {
o.getWaiter().notify();
}
}
}
}
}

public class Restaurant {
private List<Order> orderList = new ArrayList<Order>();
private Map<WaitPerson,List<Order>> readyMap = new HashMap<WaitPerson,List<Order>>();
public List<Order> getOrderList(){
return orderList;
}
public Map<WaitPerson,List<Order>> getReadyList(){
return readyMap;
}
public void newOrder(Order o){
orderList.add(o);
}
public Order getFirstOrder(){
return (orderList.size() == 0) ? null : orderList.get(0);
}
public Order newReady(WaitPerson w,Order o){
if(readyMap.get(w) != null){
readyMap.get(w).add(o);
}else{
List<Order> readyOrderlist = new ArrayList<Order>();
readyOrderlist.add(o);
readyMap.put(w, readyOrderlist);
}
orderList.remove(0);
return o;
}
public Order getReady(WaitPerson w){
List<Order> olist = new ArrayList<Order>();
olist = readyMap.get(w);
if(olist != null){
return (olist.size() == 0) ? null : olist.get(0);
}else{
return null;
}
}
public Order removeReady(WaitPerson w){
return readyMap.get(w).remove(0);
}
public static void main(String[] args){
Restaurant restaurant = new Restaurant();
WaitPerson waitPerson1 = new WaitPerson("aaa", restaurant);
WaitPerson waitPerson2 = new WaitPerson("bbb", restaurant);
WaitPerson waitPerson3 = new WaitPerson("ccc", restaurant);
WaitPerson waitPerson4 = new WaitPerson("ddd", restaurant);
Custom c1 = new Custom(1,restaurant,waitPerson4);
Custom c2 = new Custom(2,restaurant,waitPerson3);
Custom c3 = new Custom(3,restaurant,waitPerson2);
Custom c4 = new Custom(4,restaurant,waitPerson1);
Custom c5 = new Custom(5,restaurant,waitPerson4);
Custom c6 = new Custom(6,restaurant,waitPerson3);
Chef chef1 = new Chef("Jimmy",restaurant);
Chef chef2 = new Chef("Manny",restaurant);
}
}

如果是这样一种业务设定,一个顾客进店后会被指定一个服务生,然后每次订餐都会找这个服务生,那么上面的代码就可以工作。
cargoj 2012-03-14
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 xiongyu2006 的回复:]
服务生、厨师的临界资源是盘子,盘子有东西服务生就干活,没东西厨师就干活。
顾客点餐,就是要了多个盘子,
[/Quote]
厨师只会通知给他订单的那个服务生。
MiceRice 2012-03-14
  • 打赏
  • 举报
回复
确实没法同时Wait两个事件,所以要研究下你Wait的是什么,其实服务员等待的应该是个呼叫。

在你引入顾客后,这个模型其实变得比较复杂:
厨师--服务员:厨师提供做好的菜让服务员送餐;
服务员--顾客:顾客点菜后要服务员下单。

看来还是要引入命令队列,会让这个模型显得更清晰和简单点:
做个服务员的命令队列,厨师和顾客都向这个队列中放入自己的呼叫,放入后即等待该呼叫被处理。
服务员则从该队列中获取任务,根据是厨师任务还是顾客任务分别进行处理,完成后唤醒厨师或顾客,然后继续从队列找下一个任务。

这样做应该会更清晰些。。
cargoj 2012-03-14
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 ldh911 的回复:]
饿死是指:长期轮不到他抢到竞争资源,不是指某一次竞争之内抢不到。

而且服务生在没有厨师要求送餐之前,还可以继续去帮别人点菜才是。
[/Quote]
那这个设定下,服务生需要同时等待顾客点餐、厨师通知送餐。
一个线程中怎么会有两个WAIT呢?
MiceRice 2012-03-14
  • 打赏
  • 举报
回复
饿死是指:长期轮不到他抢到竞争资源,不是指某一次竞争之内抢不到。

而且服务生在没有厨师要求送餐之前,还可以继续去帮别人点菜才是。
cargoj 2012-03-14
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 ldh911 的回复:]
用标准的资源争用其实就已经能解决问题了,实际上就是谁先抢到算谁的,那么在极低概率下顾客有可能被饿死。
0

不过也可以延伸下设计,考虑增加事件队列。
相当于顾客喊服务生,就相当于发出一条指令进入队列,那么空闲服务生从指令队列中接下一个任务。
[/Quote]

不是极低概率,是一定会被饿死吧。
如果6个顾客、4个服务生,那么4个顾客点餐后4个服务生就已经在等待送餐了,这时候如果有2个顾客来,那就要等到有一个服务生已经送完餐,那不就饿死了啊。
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 ldh911 的回复:]

用标准的资源争用其实就已经能解决问题了,实际上就是谁先抢到算谁的,那么在极低概率下顾客有可能被饿死。


不过也可以延伸下设计,考虑增加事件队列。
相当于顾客喊服务生,就相当于发出一条指令进入队列,那么空闲服务生从指令队列中接下一个任务。
[/Quote]


- - !饿死了
xiongyu2006 2012-03-14
  • 打赏
  • 举报
回复
服务生、厨师的临界资源是盘子,盘子有东西服务生就干活,没东西厨师就干活。
顾客点餐,就是要了多个盘子,
昨日凡阳 2012-03-13
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 cargoj 的回复:]

在没有加入顾客的情况下,多个服务生、多个厨师由服务生自己下订单,在餐厅加入订餐LIST、准备就绪Map<Waiter,Order>后已经解决。


但是加入顾客以后,Waiter除了需要检查准备就绪Map以外还需要检查顾客订餐LIST,这该怎么处理呢?
[/Quote]

订餐LIST 这个是顾客的行为啊,顾客就是一个线程。
cargoj 2012-03-13
  • 打赏
  • 举报
回复
在没有加入顾客的情况下,多个服务生、多个厨师由服务生自己下订单,在餐厅加入订餐LIST、准备就绪Map<Waiter,Order>后已经解决。


但是加入顾客以后,Waiter除了需要检查准备就绪Map以外还需要检查顾客订餐LIST,这该怎么处理呢?
昨日凡阳 2012-03-13
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 cargoj 的回复:]

恩,我是想有人提点一下该怎么写这个代码。
[/Quote]

你要首先深刻了解多线程的内在含义。

了解实现方式。

然后将这个场景进行划分,明白什么是临界资源,明白哪些可以作为线程对象。。。。。。

明白了所有的之后,写代码就没有什么问题了。
cargoj 2012-03-13
  • 打赏
  • 举报
回复
恩,我是想有人提点一下该怎么写这个代码。
昨日凡阳 2012-03-13
  • 打赏
  • 举报
回复
你想让人再给你把这个copy一份?

67,550

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧