银行家算法代码实现简单的报告模式(JAVA实现)

习题答案和练习 专栏收录该内容
16 篇文章 8 订阅

1设计内容 
完成银行家算法的模拟实现:设计有m个进程共享n个系统资源的系统,进程可动态的申请和释放资源。系统按各进程的申请动态的分配资源时,采用银行家算法有效地避免死锁的发生。

2 分析设计
2.1 算法原理

(1)银行家算法的思路
对进程的资源请求进行合法性检查;若请求合法,则进行试分配。试分配后,调用安全性检查算法进行安全性检查。若安全,则满足该进程请求,分配资源;若不安全,则拒绝该进程申请,不分配资源,并恢复系统试分配前的资源状态。

(2)银行家算法中用到的主要数据结构
可利用资源向量 int Available[j] // j为资源的种类。
最大需求矩阵 int Max[i][j] // i为进程的数量。
分配矩阵 int Allocation[i][j]
需求矩阵 int Need[i][j]= Max[i][j]- Allocation[i][j]
申请各类资源数量 int Requesti[j] //i进程申请j资源的数量
工作向量 int Work[x] int Finish[y]

(3)银行家算法Bank()
进程i发出请求申请k个j资源,Requesti[j]=k
① 检查申请量是否小于等于需求量:
Requesti[j]<=Need[i,j],若条件不符重新输入,不允许申请大于需求量。
② 检查申请量是否小于等于系统中的可利用资源量:
Requesti[j]<=Available[j],若条件不符就申请失败,阻塞该进程,用goto语句跳转至重新申请资源。
③ 若以上两个条件都满足,则系统试探着将资源分配给申请的进程,并修改下面数据结构中的数值:
Available[j]= Available[j]- Requesti[j];
Allocation[i][j]= Allocation[i][j]+ Requesti[j];
Need[i][j]= Need[i][j]- Request i[j];
④ 试分配后,执行安全性检查,调用Safe()函数检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程;否则本次试探分配作废,恢复原来的资源分配状态,让该进程等待。
⑤ 用while循环实现输入字符Y/y判断是否继续请求资源分配。

(4)安全性检查算法(Safe()函数)
① 设置两个向量:
工作向量Work:表示系统可提供给进程继续运行所需的各类资源数目,在执行安全性算法开始时,令Work= Available。
Finish:表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]=false;当有足够的资源分配给进程时,再令Finish[i]=true。
② 在进程集合中查找符合以下条件的进程:
条件1:Finish[i]=0
条件2:Need[i][j]<=Work[j]
若找到,则执行步骤③;否则,执行步骤④
③ 当进程获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work[j]= Work[j]+ Allocation[i][j]
Finish[i]=true
跳至 ②
④ 若所有进程的Finish[i]=true都满足,则表示已找到安全序列,系统处于安全状态,试分配成功;否则,系统处于不安全状态,不予分配。

2.2 程序结构
我采用了java封装的方法,创建了两个源文件,即两个类,一个类用于完成核心算法,一个是主类用来测试的。
在这里插入图片描述

2.3 数据结构
在这里插入图片描述
2.4 程序流程图

在这里插入图片描述
2.5 关键代码
1、BankDemo.java

package Bank;
/**
 * 
 * 银行家算法
 * @author Monster丶ZF
 * @version1.8
 * @data 2019年7月1日
 * @remakeTODO
 */
import java.util.Scanner;

public class BankDemo{

    int[] Available = {3, 12, 14,14};  //用来存系统初始状态未分配时的可用资源量
    int[][] Max = new int[5][4];           //用来存取进程最大需求矩阵
    int[][] Alloction = new int[5][4];      //用来存取进程已经分配资源的矩阵
    int[][] Need = new int[5][4];           //用来存取各进程还需要的资源的矩阵
    int[][] Request = new int[5][4];       	//用来存取用户输入的要检测的进程号和各类资源
    int[] Work = new int[4];                //用来检测系统安全性的

    int num = 0;          //进程编号(全局变量)
    Scanner input = new Scanner(System.in);


    
    /**
     * 设置各初始系统变量,并判断是否处于安全状态。
     */
    public void setMatrixVariable(){ //设置各类矩阵变量的方法
        setMax();         //调用设置各进程的最大需求矩阵Max
        setAlloction();   //调用各进程分配矩阵Alloction,
        printMatrixVariable();//调用打印设置好的各类矩阵
        Safe();               //调用安全性算法检测
    }
    
    
     /**
      * 设置Max矩阵
      */
    public void setMax() {
        System.out.println("请设置各进程的最大需求矩阵Max:");
        for (int i = 0; i < 5; i++) {
            System.out.println("请输入进程P" + i + "的最大资源需求量:");
            for (int j = 0; j < 4; j++) {
                Max[i][j] = input.nextInt();
            }
        }
    }
    
    
     /**
      * 设置已分配矩阵Alloction
      */
    public void setAlloction() {
        System.out.println("请设置请各进程分配矩阵Alloction:");
        for (int i = 0; i < 5; i++) {
            System.out.println("请输入进程P" + i + "的分配资源量:");
            for (int j = 0; j < 4; j++) {
                Alloction[i][j] = input.nextInt();
            }
        }
        System.out.println("Available=Available-Alloction.");
        System.out.println("Need=Max-Alloction.");
        for (int i = 0; i < 4; i++) {//设置Available矩阵
            for (int j = 0; j < 5; j++) {
                Available[i] = Available[i] - Alloction[j][i];
            }
        }
        for (int i = 0; i < 5; i++) {//设置Need矩阵
            for (int j = 0; j < 4; j++) {
                Need[i][j] = Max[i][j] - Alloction[i][j];
            }
        }
    }
    
      /*
       * 把初始化或设置好的各矩阵打印出来
       */
    public void printMatrixVariable(){
        System.out.println("此时资源分配量如下:");
        System.out.println("进程 \t"+ "Max\t"+"    Alloction\t"+"    Need\t"+ "    Available");
        for(int i=0;i<5;i++){
            System.out.print("P"+i+"  ");
            for(int j=0;j<4;j++){
               System.out.print(Max[i][j]+"  "); 
            }
            System.out.print("|  ");
            for(int j=0;j<4;j++){
               System.out.print(Alloction[i][j]+"  "); 
            }
            System.out.print("|  ");
            for(int j=0;j<4;j++){
               System.out.print(Need[i][j]+"  "); 
            }
            System.out.print("|  ");
            if(i==0){
                for(int j=0;j<4;j++){
                    System.out.print(Available[j]+"  ");
                }
            }
            System.out.println();
        }
    }
      /**
       * 设置请求资源量Request
       */
    public void setRequest() {
        System.out.println("请输入请求资源的进程编号:");
        num= input.nextInt();//设置全局变量进程编号num
        System.out.println("请输入请求各资源的数量:");
        for (int j = 0; j < 4; j++) {
            Request[num][j] = input.nextInt();
        }
        System.out.println("即进程P" + num + "对各资源请求Request:(" + Request[num][0] + "," + Request[num][1] + "," + Request[num][2] + "," + Request[num][3] + ").");

        BankerAlgorithm();//调用银行家算法
    }
  
     /**
      * 实现银行家算法功能
      */
    public void BankerAlgorithm() {
        boolean T=true;

        if (Request[num][0] <= Need[num][0] && Request[num][1] <= Need[num][1] && Request[num][2] <= Need[num][2]&&Request[num][3] <= Need[num][3]) {//判断Request是否小于Need
            if (Request[num][0] <= Available[0] && Request[num][1] <= Available[1] && Request[num][2] <= Available[2]&&Request[num][3] <= Available[3]) {//判断Request是否小于Alloction
                for (int i = 0; i < 4; i++) {
                    Available[i] -= Request[num][i];
                    Alloction[num][i] += Request[num][i];
                    Need[num][i] -= Request[num][i];
                }

            } else {
                System.out.println("当前没有足够的资源可分配,进程P" + num + "需等待。");
               T=false;
            }
        } else {
            System.out.println("进程P" + num + "请求已经超出最大需求量Need.");
            T=false;
        }

       if(T==true){
        printMatrixVariable();
        System.out.println("现在进入安全算法:"); 
        Safe();
       }
    }

    /**
     * 实现安全性检查功能
     */
    public void Safe() {//安全算法
        boolean[] Finish = {false, false, false,false,false};//初始化Finish
        int count = 0;  //完成进程数
        int circle= 0;   //循环圈数
        int[] S=new int[5]; //安全序列
        for (int i = 0; i < 4; i++) { //设置工作向量
            Work[i] = Available[i];
        }
        boolean flag = true;
        while (count < 5) {
            if(flag){
                System.out.println("进程 \t"+"Work\t"+ "    Alloction\t"+"    Need\t"+"    Work+Alloction");
                flag = false;
            }
            for (int i = 0; i < 5; i++) {

                if (Finish[i]==false&&Need[i][0]<=Work[0]&&Need[i][1]<=Work[1]&&Need[i][2]<=Work[2]&&Need[i][3]<=Work[3]) {//判断条件
                    System.out.print("P"+ i +"  ");
                    for (int k = 0; k < 4; k++){
                        System.out.print(Work[k]+"  ");
                    }
                    System.out.print("|  ");
                    for (int j = 0; j < 4;j++){
                    Work[j]+=Alloction[i][j];
                    }
                    Finish[i]=true;//当前进程能满足时
                    S[count]=i;//设置当前序列排号

                    count++;//满足进程数加1
                    for(int j=0;j<4;j++){
                       System.out.print(Alloction[i][j]+"  "); 
                    }
                    System.out.print("|  ");
                    for(int j=0;j<4;j++){
                       System.out.print(Need[i][j]+"  "); 
                    }
                    System.out.print("|  ");
                    for(int j=0;j<4;j++){
                       System.out.print(Work[j]+"  "); 
                    }
                    System.out.println();
                }

            }
            circle++;//循环圈数加1
            if(count==5){//判断是否满足所有进程需要
                System.out.print("此时存在一个安全序列:");
                for (int i = 0; i<5;i++){//输出安全序列
                    System.out.print("P"+S[i]+" ");
                }
                System.out.println("故当前可分配!");
                break;//跳出循环
            }
            if(count<circle){//判断完成进程数是否小于循环圈数
                count=Integer.MAX_VALUE;//设置一个不可能的数跳出循环
      
               System.out.println("尝试分配后当前系统处于不安全状态,故不存在安全序列。所以应该取消分配!!"); 
               
               System.out.println("----------------------------------------------------------------");
                for (int i = 0; i < 4; i++) {
                    Available[i] += Request[num][i]; //如果不存在安全序列就撤销分配
                    Alloction[num][i] -= Request[num][i];
                    Need[num][i] += Request[num][i];
                }
                printMatrixVariable();
                //break;//跳出循环
            }
        }
    }

}

2、BankDemoTest.java

package Bank;
import java.util.Scanner;
/**
 * 银行家测试类
 * @author Monster丶ZF
 * @version1.8
 * @data 2019年7月1日
 * @remakeTODO
 */
public class BankDemoTest{
    public static void main(String[] args) {
        boolean Choose = true; // 用来控制是否继续的循环
        final String C = "n";  //字符串常量  
        String Choice;   //用来保存用户的选择
        Scanner input = new Scanner(System.in);
        BankDemo bank = new BankDemo(); //创建一个BankDemo类的对象
        System.out.println("这是一个五个进程,初始系统可用四类资源为{3,12,14,14}的银行家算法:");
        bank.setMatrixVariable();   //调用方法初始化各类矩阵
        while (Choose == true) {
            bank.setRequest();
            System.out.println("您是否还要进行请求:Y(y)/N(n)?");
            Choice = input.nextLine();
            if (C.equalsIgnoreCase(Choice)) {  //忽略大小写
            	System.out.println("已成功退出程序!");
                Choose = false;
            }
        }
        input.close();
    }
}

3 运行结果及分析

3.1 测试数据
系统有5个进程(p0,p1,p2,p3,p4)和4类资源(A,B,C,D),在T0时刻的资源分配情况如下表所示:
在这里插入图片描述
3.2 运行结果截图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.3 运行分析

(1)答:由前面两个截图可知道当初始化好各进程需要的最大需求量Max矩阵和各进程已经分配好的Allocation矩阵后,系统就会根据公式把Available矩阵和Need矩阵求出来,然后调用打印的方法把此时系统的各类矩阵的状态打印到屏幕上,接着会调用进入安全性检查Safe()方法,可知道当前状态是安全,存在一个安全序列P0 P3 P4 P1 P2,随便解释下打印下的第一句,那里也提到到,3,12,14,14是系统未分配给任何进程时的资源数量,是用前面 int[] Available = {3, 12, 14,14};来存放的。就是用1,6,2,2加上Alloction已分配各类资源就好。

(2)由第三张张截图可以看到,先是输入了提出申请资源的进程编号2及代表P2,在输入相应的请求各类资源的数量,接着就会尝试性分配,把分配后的各类的矩阵的打印到屏幕上,在调用安全性算法Safe()检测是否安全,结果是不安全的,所有要撤销之前的分配,在调用一次打印的方法,把撤销后的状态也打印到屏幕上,接着可以继续输入请求资源申请的进程编号,直到用户输入N或n,可以或略大小写,如最后一张截图。

  • 5
    点赞
  • 1
    评论
  • 38
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:马嘣嘣 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值