黑马程序员技术交流社区

标题: 求教妈妈做饭,小明买盐 这样写代码可以吗 [打印本页]

作者: wangliujieok    时间: 2013-4-7 13:04
标题: 求教妈妈做饭,小明买盐 这样写代码可以吗
模拟妈妈做饭,做饭时发现没有盐了,让儿子去买盐(假设买盐需要3分钟),只有盐买回来之后,妈妈才能继续做饭的过程。
@author Administrator

请教:这样写代码符合题目要求吗? 请大师给予指点

class Mather implements Runnable
{
        //private static boolean ture;
        private  boolean b = false;
        public void run()
        {
                if(b)
                {
                        System.out.println("有盐了.....");
                        System.out.println("妈妈做饭.....");
                        return;
                }
                if(!b)
                {
                        System.out.println("没有盐了....");
                        System.out.println("妈妈暂停做饭....");
                        try
                        {
                                Thread.sleep(1800);
                        }
                        catch (InterruptedException e)
                        {
                                e.printStackTrace();
                        }
                        System.out.println("妈妈让儿子去买盐....");
                }
                Son.run();       
        }
}
class  Son//implements Runnable
{
        public static void run()
        {
                System.out.println("儿子去买盐.....");
                 System.out.println("盐买回来了.....");
                 System.out.println("儿子叫妈妈继续做饭.....");
        }
}
class MakeDinner
{
        public static void main(String[] args)
        {
                Mather mother = new Mather();
                Thread t1 = new Thread(mother);
                t1.start();
        }
}



作者: 冯超    时间: 2013-4-7 13:06
看看······!!!!!!!!!!!!!!!!
作者: 张洪慊    时间: 2013-4-7 14:43
本帖最后由 张洪慊 于 2013-4-7 16:25 编辑

个人感觉利用等待唤醒机制更好点:
下面仅供参考(每个人思路不同,能实现就行,复习下线程0.0)
  1. /*
  2. 需求:
  3. 模拟妈妈做饭,做饭时发现没有盐了,
  4. 让儿子去买盐(假设买盐需要3分钟),
  5. 只有盐买回来之后,妈妈才能继续做饭的过程。

  6. 分析:(可以利用等待唤醒机制)
  7. 共享资源:盐
  8. 两个线程:妈妈 和 儿子
  9. 这里的 妈妈 和 儿子 分别相当于
  10.       消费者  生产者 模型
  11. 思想:
  12. ①把盐,妈妈和儿子都单独封装为一个类,分别描述

  13. ②由于妈妈和儿子中有线程要运行的代码,
  14.   因此使妈妈和儿子实现Runnable接口,复写run方法

  15. ③利用等待唤醒机制即
  16.   当妈妈发现没盐了(wait),唤醒(notify)儿子去买盐
  17.   当儿子买回来盐,唤醒妈妈去做饭
  18. */
  19. //盐类
  20. class Salt{
  21.   private boolean flag=false;//设置一个共享标记
  22.   public Salt(){}
  23.   public boolean getFlag(){//获取当前标记值
  24.   
  25.    return flag;
  26.   }
  27.   public boolean changeFlag(boolean flag){//对外提供一个改变标记的方法
  28.      
  29.          return this.flag=flag;
  30.   }

  31. }
  32. //妈妈类
  33. class Mom implements Runnable{
  34.   private Salt s;//在内部使用盐对象
  35.   public Mom(Salt s){
  36.     this.s=s;
  37.   }
  38.   public void run(){ //使用同步函数,因为下面要用到wait,notify,指明锁
  39.     while(true){
  40.           synchronized(s){
  41.        if(!s.getFlag()){//由于只有一个线程执行该run方法,采用if判断
  42.                
  43.                    System.out.println("①妈妈说:没盐了,儿子买盐去吧,妈妈等着你");
  44.                    s.notify();//唤醒同一个锁上的儿子
  45.                    try{s.wait(3*60*1000);
  46.                   
  47.                    }
  48.                    catch(Exception e){
  49.                   
  50.                    e.printStackTrace();
  51.                    }
  52.                  
  53.                
  54.             }
  55.                 System.out.println("③好儿子,盐买回来了,妈妈接着给你做饭");
  56.              s.changeFlag(false);//以上做完饭,买的盐用完.
  57.           }
  58.       
  59.    }
  60.       
  61. }
  62. }
  63. //儿子类
  64. class Son implements Runnable{
  65. private Salt s;
  66.   public Son(Salt s){
  67.     this.s=s;
  68.   }
  69.   public void run(){
  70.     while(true){
  71.          synchronized(s){
  72.        if(!s.getFlag()){//没盐->儿子去买
  73.                   
  74.                    System.out.println("②好的妈妈,你等一会哈,我这就去");
  75.                    s.changeFlag(true);//如果再次执行,儿子不在买盐
  76.                    s.notify();//已有盐 唤醒妈妈做饭
  77.                    try{s.wait();
  78.                   
  79.                    }
  80.                    catch(Exception e){
  81.                    e.printStackTrace();
  82.                    }
  83.                 }
  84.         }
  85.    
  86.    
  87.    }
  88.       
  89. }

  90. }
  91. class BuySaltTest{
  92.   public static void main(String[] args){
  93.   
  94.    Salt s=new Salt();
  95.    //分别创建两个线程执行指定接口子类对象run方法
  96.    new Thread(new Mom(s)).start();
  97.    new Thread(new Son(s)).start();
  98.   }


  99. }
复制代码

作者: 随便    时间: 2013-4-7 15:53
本帖最后由 邓宫财 于 2013-4-7 15:55 编辑
  1. public class SaltTest {
  2.         public static void main(String[] args) {
  3.                 //定义做饭的对象
  4.                 final Cook c = new Cook();         
  5.                 //定义一个妈妈做饭的线程,并启动
  6.                 new Thread(new Runnable() {
  7.                         public void run() {
  8.                                 while(true){
  9.                                         c.makeCook();
  10.                                 }
  11.                         }
  12.                 }).start();
  13.                 //定义一个儿子买盐的线程,并启动
  14.                 new Thread(new Runnable() {
  15.                         public void run() {
  16.                                 while(true){
  17.                                         c.buySalt();
  18.                                 }
  19.                         }
  20.                 }).start();
  21.         }
  22. }
  23. /**
  24. * 因为妈妈儿子需要用到相同的锁对象,和相同的是否能做饭的标示对戏那个,所以把他们封装在一个类中的两个方法中。
  25. * @author Dgc
  26. */
  27. class Cook{
  28.         //是否能做饭的标识
  29.         private boolean canCook = false;
  30.         
  31.         /**
  32.          * 妈妈做饭的方法
  33.          */
  34.         public synchronized void makeCook(){
  35.                 //如果没有盐,就等待3分钟,唤醒儿子去买盐。
  36.                 if(!canCook){
  37.                         System.out.println("没有盐,不能做饭...");
  38.                         System.out.println("等待买盐....");
  39.                         try {
  40.                                 this.notify();
  41.                                 Thread.sleep(1000 * 3 * 60);
  42.                                 this.wait();
  43.                         } catch (InterruptedException e) {
  44.                                 e.printStackTrace();
  45.                         }
  46.                 }
  47.                 //能做饭了。做完之后,把变量设置回去。
  48.                 System.out.println("妈妈正在做饭。。。");
  49.                 canCook = false;
  50.         }
  51.         /**
  52.          * 儿子买盐的方法
  53.          */
  54.         public synchronized void buySalt(){
  55.                 //如果能做饭,儿子就休息
  56.                 if(canCook){
  57.                         try {
  58.                                 this.wait();
  59.                         } catch (InterruptedException e) {
  60.                                 e.printStackTrace();
  61.                         }
  62.                 }
  63.                 //如果没有盐,儿子去买盐并唤醒妈妈,把能做饭设置true
  64.                 System.out.println("儿子去买盐了,");
  65.                 canCook = true;
  66.                 this.notify();
  67.         }
  68. }
复制代码

作者: wangliujieok    时间: 2013-4-7 16:30
邓宫财 发表于 2013-4-7 15:53

多谢各位大师,代码及思路看明白了  线程我才学了一半:lol
作者: 随便    时间: 2013-4-7 16:39
wangliujieok 发表于 2013-4-7 16:30
多谢各位大师,代码及思路看明白了  线程我才学了一半

加油。共同学习,共同进步。
作者: Bule_Silence    时间: 2013-7-13 12:05
我觉得本题考查的不是多线程通信问题,大家把问题想复杂了,仅仅考查的就是java基础。
  1. /*
  2. 需求:
  3. 模拟妈妈做饭,做饭时发现没有盐了,
  4. 让儿子去买盐(假设买盐需要3分钟),
  5. 只有盐买回来之后,妈妈才能继续做饭的过程。

  6. 分析:(可以利用等待唤醒机制)
  7. 共享资源:盐
  8. 两个线程:妈妈 和 儿子
  9. 这里的 妈妈 和 儿子 分别相当于
  10.       消费者  生产者 模型
  11. 思想:
  12. ①把盐,妈妈和儿子都单独封装为一个类,分别描述

  13. ②由于妈妈和儿子中有线程要运行的代码,
  14.   因此使妈妈和儿子实现Runnable接口,复写run方法

  15. ③利用等待唤醒机制即
  16.   当妈妈发现没盐了(wait),唤醒(notify)儿子去买盐
  17.   当儿子买回来盐,唤醒妈妈去做饭
  18. */
  19. //盐类
  20. class Salt{
  21.   private boolean flag=false;//设置一个共享标记
  22.   public Salt(){}
  23.   public boolean getFlag(){//获取当前标记值
  24.   
  25.    return flag;
  26.   }
  27.   public boolean changeFlag(boolean flag){//对外提供一个改变标记的方法
  28.      
  29.          return this.flag=flag;
  30.   }

  31. }
  32. //妈妈类
  33. class Mom implements Runnable{
  34.   private Salt s;//在内部使用盐对象
  35.   public Mom(Salt s){
  36.     this.s=s;
  37.   }
  38.   public void run(){ //使用同步函数,因为下面要用到wait,notify,指明锁
  39.     while(true){
  40.           synchronized(s){
  41.        if(!s.getFlag()){//由于只有一个线程执行该run方法,采用if判断
  42.                
  43.                    System.out.println("①妈妈说:没盐了,儿子买盐去吧,妈妈等着你");
  44.                    s.notify();//唤醒同一个锁上的儿子
  45.                    try{s.wait(3*60*1000);
  46.                   
  47.                    }
  48.                    catch(Exception e){
  49.                   
  50.                    e.printStackTrace();
  51.                    }
  52.                  
  53.                
  54.             }
  55.                 System.out.println("③好儿子,盐买回来了,妈妈接着给你做饭");
  56.              s.changeFlag(false);//以上做完饭,买的盐用完.
  57.           }
  58.       
  59.    }
  60.       
  61. }
  62. }
  63. //儿子类
  64. class Son implements Runnable{
  65. private Salt s;
  66.   public Son(Salt s){
  67.     this.s=s;
  68.   }
  69.   public void run(){
  70.     while(true){
  71.          synchronized(s){
  72.        if(!s.getFlag()){//没盐->儿子去买
  73.                   
  74.                    System.out.println("②好的妈妈,你等一会哈,我这就去");
  75.                    s.changeFlag(true);//如果再次执行,儿子不在买盐
  76.                    s.notify();//已有盐 唤醒妈妈做饭
  77.                    try{s.wait();
  78.                   
  79.                    }
  80.                    catch(Exception e){
  81.                    e.printStackTrace();
  82.                    }
  83.                 }
  84.         }
  85.    
  86.    
  87.    }
  88.       
  89. }

  90. }
  91. class BuySaltTest{
  92.   public static void main(String[] args){
  93.   
  94.    Salt s=new Salt();
  95.    //分别创建两个线程执行指定接口子类对象run方法
  96.    new Thread(new Mom(s)).start();
  97.    new Thread(new Son(s)).start();
  98.   }


  99. }
复制代码
会无限循环下去,很明显题意就是简单地让做饭停止3分钟,然后继续执行,根本就不需要多线程通信来完成。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2