用Java实现PV操作——父亲女儿吃水果问题

在学习操作系统的进程的同步操作中,老师有道实验题,要求使用信号量完成父亲女儿吃水果问题。基于C系语言对我的不友好,我询问了老师能否使用Java实现(因为Java里边好多方法都是现成的,不用自己写~~),距离学习Java线程已经过了快一年,刚好复习复习。

【问题描述】桌上有一空盘,最多允许存放一个水果。爸爸可向盘中放一个苹果或放一个桔子,儿子专等吃盘中的桔子,女儿专等吃苹果。 试用P、V操作实现爸爸、儿子、女儿三个并发进程的同步。 提示:设置一个信号量表示可否向盘中放水果,一个信号量表示可否取桔子,一个信号量表示可否取苹果。

问题分析

  • 桌子上只有一个盘子,父亲每次只能放入一种水果,同一时间内,盘子里只能有一种水果
  • 儿子和女儿从盘子里拿水果,水果只有一个,同一时间内只有一个人吃水果,所以儿子和女儿也是互斥关系
  • 父亲放何种水果制约了女儿和儿子取何种水果

Java中的Semaphore

//此信号量获得一个许可,在提供一个许可前将线程堵塞,否则线程被中断。获得一个许可并立即返回,将许可数减一
  public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
//释放一个许可,将其返回给信号量。将可用的许可数加一
 public void release() {
        sync.releaseShared(1);
    }

也就是说,在初始化一个信号量的时候,例如构造函数: Semaphore Semaphore = new Semaphore(1); 信号量的许可数为1,每acquire一次,许可数就 -1,每release一次,许可数就+1,当许可数变为0还acquire的话,该线程会进入阻塞状态,直到release方法将许可数置为1,才能执行

实例代码

package thread;

import java.util.concurrent.Semaphore;

/**
 * @ClassName App
 * @Author hobo
 * @Date 19-4-17 下午3:37
 * @Description
 **/
public class App {

    //初始化桌子为空的信号量为1 使父亲线程能够运行  1 桌子为空,0 桌子不为空
    public static Semaphore diskEmpty = new Semaphore(1);

    //初始化信号量为0,使得女儿和儿子的进程阻塞
    public static Semaphore haveOrange = new Semaphore(0);

    public static Semaphore haveApple = new Semaphore(0);

    public static void main(String[] args) {
        Father father = new Father();
        Son son = new Son();
        Daughter daughter = new Daughter();

        father.start();
        son.start();
        daughter.start();
    }

}

父亲线程

package thread;

import java.util.Random;

/**
 * @ClassName Father
 * @Author hobo
 * @Date 19-4-17 下午3:36
 * @Description
 **/
public class Father extends Thread {

    @Override
    public void run() {
        try {
            while (true) {
                //使用随机数控制父亲放入橘子还是苹果
                Random random = new Random();
                int n = random.nextInt(100);

                App.diskEmpty.acquire();
                if (n % 2 == 0) {
                    Disk.putFruit("橘子");
                    App.haveOrange.release();
                } else {
                    Disk.putFruit("苹果");
                    App.haveApple.release();
                }
                sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

儿子线程

package thread;

/**
 * @ClassName Son
 * @Author hobo
 * @Date 19-4-17 下午3:36
 * @Description
 **/
public class Son extends Thread {

    private static String name = "儿子";

    @Override
    public void run() {

        try {
            while (true) {
                App.haveOrange.acquire();
                Disk.getFruit(name);

                sleep(1000);

                App.diskEmpty.release();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

女儿线程

package thread;

/**
 * @ClassName Daughter
 * @Author hobo
 * @Date 19-4-17 下午3:37
 * @Description
 **/
public class Daughter extends Thread {

    private static String name = "女儿";

    @Override
    public void run() {
        try {
            while (true) {
                App.haveApple.acquire();
                Disk.getFruit(name);
                sleep(1000);
                App.diskEmpty.release();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

盘子

package thread;

/**
 * @ClassName Disk
 * @Author hobo
 * @Date 19-4-17 下午3:37
 * @Description
 **/
public class Disk {

    private static String fruitName = "";

    public static void putFruit(String fruit) {
        fruitName = fruit;
        System.out.println("父亲往盘子里边放了一个" + fruit);
    }

    public static String getFruit(String name) {
        System.out.println(name + "吃了一个" + fruitName);
        return fruitName;
    }
}

运行结果
在这里插入图片描述
Github传送门

  • 11
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值