java 与操作系统同步问题(三)————父亲儿子女儿水果问题

  问题描述:父亲每次都会放一个水果在桌子上,女儿喜欢吃香蕉(只吃香蕉), 儿子喜欢吃苹果(只吃苹果)。父亲每次只会随机往桌子上放一个水果(苹果或香蕉),儿子,女儿会来取。使用p、v操作来完成父亲、儿子、女儿的同步行为模拟。

  问题分析:由上述描述我们可以知道,桌子就是一个缓冲区(单缓冲),同一时刻,只能有一个人对它进行放和取得操作。所以桌子就是一个互斥信号量。而桌子上有苹果,且父亲没有放,儿子才能取,女儿也是同理。所以应该还有两个资源信号量:1 苹果 2 香蕉

在由题意分析可知,三个信号量的初始值应该为 1 0 0 因为桌子只能放一个水果。而在开始的时候,桌子上是空的(所以可以进行放的操作),所以苹果、香蕉初始资源量都为空。

  代码实现:

       1.信号量设定如下:

    /**
     * 缓冲区是否满信号量
     */
    Semaphore empty;
    
    /**
     * 苹果信号量
     */
    Semaphore apple;
    
    /**
     * 香蕉信号量
     */
    Semaphore banana;


empty = new Semaphore(1);
apple = new Semaphore(0);
banana = new Semaphore(0);

 

       2.父亲的放的线程,只有在桌子互斥资源量可以用的时候才能进行放的操作。所以要先p一下桌子信号量。

       

Thread fatherThread = new Thread(new Runnable() {
        String className = "father";
        
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true) {
                Semaphore.Wait(empty, className);
                if (randomAB()) {
                    System.out.println(className + "往盘子里放了一个苹果");
                    Semaphore.Signal(apple, className);
                } else {
                    System.out.println(className + "往盘子里放了一个香蕉");
                    Semaphore.Signal(banana, className);
                }
                System.out.println(className + "完成了一次放的操作");
                //随机生成休眠时间,代表放入产品的操作时间
                long millis = (long) (Math.random() * 1000);
                try {
                    Thread.sleep(millis);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
                
            }
        }
    });

       3.儿子的实现,要判断是否有苹果,没有的话就等待

    Thread sonThread = new Thread(new Runnable() {
        String className = "son";
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true) {
                Semaphore.Wait(apple, className);
                System.out.println(className + "从盘子里取了一个苹果");
                //随机生成休眠时间,代表放入产品的操作时间
                long millis = (long) (Math.random() * 1000);
                try {
                    Thread.sleep(millis);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(className + "吃了一个苹果");
                Semaphore.Signal(empty, className);
                System.out.println(className + "完成了一次取吃的操作");
            }
        }
    });

      4.女儿的代码实现:原理跟儿子的类似

    Thread daughterThread = new Thread(new Runnable() {
        String className = "daughter";
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true) {
                Semaphore.Wait(banana, className);
                System.out.println(className + "从盘子里取了一个香蕉");
                //随机生成休眠时间,代表放入产品的操作时间
                long millis = (long) (Math.random() * 1000);
                try {
                    Thread.sleep(millis);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(className + "吃了一个香蕉");
                Semaphore.Signal(empty, className);
                System.out.println(className + "完成了一次取吃的操作");
            }
        }
    });

 

运行结果如下:

daughter被阻塞
son被阻塞
father往盘子里放了一个香蕉
father资源量足够,唤醒一个
father完成了一次放的操作
daughter从盘子里取了一个香蕉
daughter吃了一个香蕉
daughter完成了一次取吃的操作
daughter被阻塞
father往盘子里放了一个香蕉
father资源量足够,唤醒一个
father完成了一次放的操作
daughter从盘子里取了一个香蕉
father被阻塞
daughter吃了一个香蕉
daughter资源量足够,唤醒一个
daughter完成了一次取吃的操作
....

 

posted @ 2017-03-15 17:57  初心丶  阅读(4541)  评论(0编辑  收藏  举报