用Java实现银行家算法

用Java实现银行家算法

一、银行家算法

  银行家算法是这样一种资源分配算法:系统给进程分配资源时,先检查状态是否安全,方法是看它是否有足够的剩余资源满足一个距最大需求最近的进程。
  如果有,那么分配资源给该进程,然后接着检查下一个距最大需求最近的进程,如此反复下去。如果所有进程都能获得所需资源,那么该状态是安全的,最初的进程申请资源可以分配。

二、算法所需的数据结构

  1. Available 表示当前系统可以使用的资源数,使用一维数组来存储
  2. Request 表示进程向系统申请的各类资源数。使用一维数组实现
  3. Max 表示当前进程最大需求的资源,使用Java的HashMap存储
  4. Allocatio 表示当前进程占有的资源数,使用Java的HashMap存储
  5. Need 表示当前资源还需的资源数,使用Java的HashMap存储

三、银行家算法的算法步骤

当进程向系统申请资源的时候,系统会按照下列步骤进行检查:

  1. 如果Requst <= Need,进入第二步。否则说明进程的对资源的申请量大于它的最大值,返回False。
  2. 如果 Request <= Available,进入第三步。否则说明系统没有足够的资源可以分配,进程需等待。返回False。
  3. 系统尝试将资源分配给进程:
     Available = Available - Request;
     Allocation = Allocation + Request;
     Need = Need - Request;、
  4. 系统执行安全性检查算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程已完成此次分配;若不安全,试探性分配作废,恢复资源分配情况。让进程等待。
    安全性检查算法描述:
     定义两个结构 Free(表示系统可用资源数),Finish(表示进程某次检查是否满足)
      (1) 初始化 Free = Available,Finish所有进程为False
      (2)从进程集合中找出一个能满足下述条件的进程
         1.进程在Finish中对应的值是false(表示资源未分配给进程)
         2.进程 Need <= Free (表示资源能够分配给进程)
      (3)当进程获得资源后,认为进程完成任务,释放资源。
         Free = Free + Allocation
         Finish= true
         跳转到步骤(2)继续执行
     经过遍历一个轮回后,若可以达到,Finish中所有进程都是true。则表示系统处于安全状态,否则系统处于不安全状态。

四、银行家算法的代码实现

根据上面的算法步骤我们可以Java来实现算法步骤。

package test.tt;


import Untils.ArrayOperation;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.zip.DataFormatException;

/**
 * @author Hognhu
 * @Dataon 2020/10/17
 * 银行家算法
 *
 *
 */


public class BlankerAlgorithm {


    public Boolean RunBlankerAlgorithm( String PID,
                                         int[] Request,
                                         int[] Available,
                                         HashMap<String ,int []> Max,
                                         HashMap<String ,int []> Allocation,
                                         HashMap<String ,int []> Need) throws DataFormatException {

            //第一步 判断是不是超过自己的最大值
            if(ArrayOperation.ComparaArray(Request,Max.get(PID)))
               return false;

            //第二步判断系统有没有符合请求的数据
            if(!ArrayOperation.ComparaArray(Available,Request))
                return false;

            //第三步尝试分配
            Available = ArrayOperation.subtraction(Available,Request);
            Allocation.replace(PID,ArrayOperation.addition(Allocation.get(PID),Request));
            Need.replace(PID,ArrayOperation.subtraction(Need.get(PID),Request));

             //构建Finished
             String[] keys = getKeys(Max);
             HashMap<String ,Boolean> Finished = CreateFalse(keys);

             //检查是否安全
             if(!SecurityCheck(Finished,Available,Allocation,Need)){
                 //如果不安全,归还资源
                 return false;
             }
            return true;
    }

    //内循环
    private Boolean SecurityCheck(HashMap<String ,Boolean> FalseMap,
                             int[] Available,
                             HashMap<String ,int []> Allocation,
                             HashMap<String ,int []> Need){
        //判断size 是否为 0
        if(Need.size() == 0)
            return true;

        Iterator<Map.Entry<String ,int []>> it = Need.entrySet().iterator();

        int[] Free = Available;

        while(it.hasNext()){

           String PID =  it.next().getKey();
           int[] needProcess = Need.get(PID);

           if(!FalseMap.get(PID) && ArrayOperation.ComparaArray(Free,needProcess)) {
               //设置标志
               FalseMap.replace(PID,false);
               //释放资源
               Free =ArrayOperation.addition(Free,Allocation.get(PID));
               //释放资源
               it.remove();
               Allocation.remove(PID);
               System.out.println("PID="+PID);
               //使用递归来遍历各个进程
               Boolean result = SecurityCheck(FalseMap,Free,Allocation,Need);

               if(result)
                   return true;
           }
        }

        return false;
    }

    //创建Finish
    private HashMap<String ,Boolean> CreateFalse(String[] keys){
        HashMap<String ,Boolean> result = new HashMap<String,Boolean>();
        for(String item:keys){
            result.put(item,false);
        }
        return result;
    }

    //获取所有进程
    private String[] getKeys(Map map){
        Set<String> set1 = map.keySet();
        int size = map.size();
        String[] result = new String[size];
         int i = 0;
         for(String key:set1){
             //System.out.println(key);
             result[i] = key;
             i++;
         }
        return result;
    }

    public static void main(String[] args) throws DataFormatException {
		//测试银行家算法
        BlankerAlgorithm b = new BlankerAlgorithm();
        int[] Available = {3,3,2};
        //int[] Available = {2,3,0};
        int[] request = {1,0,2};
        //int[] request = {0,2,0};
        //int[] request = {3,3,0};
        HashMap<String,int []> Max = new HashMap();
        int [] p0 = {7,5,3};
        int [] p1 = {3,2,2};
        int [] p2 = {9,0,2};
        int [] p3   = {2,2,2};
        int [] p4 = {4,3,3};
        Max.put("p0",p0);
        Max.put("p1",p1);
        Max.put("p2",p2);
        Max.put("p3",p3);
        Max.put("p4",p4);
        HashMap<String,int []> Allocation = new HashMap();
        int [] p00 = {0,1,0};
        int [] p11 = {2,0,0};
        //int [] p11 = {3,0,2};
        int [] p22 = {3,0,2};
        int [] p33 = {2,1,1};
        int [] p44 = {0,0,2};
        Allocation.put("p0",p00);
        Allocation.put("p1",p11);
        Allocation.put("p2",p22);
        Allocation.put("p3",p33);
        Allocation.put("p4",p44);
        HashMap<String,int []> Need = new HashMap();
        int [] p000 = {7,4,3};
        int [] p111 = {1,2,2};
        int [] p222 = {6,0,0};
        int [] p333 = {0,1,1};
        int [] p444 = {4,3,1};
        Need.put("p0",p000);
        Need.put("p1",p111);
        Need.put("p2",p222);
        Need.put("p3",p333);
        Need.put("p4",p444);
        System.out.println("安全序列为:");
        System.out.println(b.RunBlankerAlgorithm("p1",request,Available,Max,Allocation,Need));
    }
}

所使用的工具类ArrayOperation

package Untils;

import org.apache.log4j.Logger;

/**
 * @author Hognhu
 * @Dataon 2020/10/17
 */


public class ArrayOperation {

    static Logger log = Logger.getLogger(ArrayOperation.class);

    /**
     * 返回 arr1 + arr2
     */
    public static int[] addition(int[] arr1, int[] arr2) {

        int size = arr1.length;

        if (size != arr2.length) throw new NumberFormatException("数组长度不一致!");

        //初始化
        int[] result = new int[size];

        for (int i = 0; i < size; i++) {
            result[i] = arr1[i] + arr2[i];
        }

        return result;
    }

    /**
     * 返回 arr1 - arr2
     */
    public static int[] subtraction(int[] arr1, int[] arr2) {

        int size = arr1.length;
        if (size != arr2.length) throw new NumberFormatException("数组长度不一致!");
        //初始化
        int[] result = new int[size];

        for (int i = 0; i < size; i++) {
            result[i] = arr1[i] - arr2[i];
        }

        return result;
    }

    /**
     * 两个数组大小
     **/
    public static Boolean ComparaArray(int[] arr1, int[] arr2) {

        Boolean result = true;
        int size = arr1.length;
        if (size != arr2.length) throw new NumberFormatException("数组长度不一致!");

        for (int i = 0; i < size; i++) {
            if (arr1[i] - arr2[i] < 0)
                result = false;
        }

        return result;
    }
	//数组数值取半
    public static int[] arrayHalve(int[] arr1) {

        int[] result = arr1.clone();
        int size = arr1.length;
        for (int i = 0; i < size; i++) {
            result[i] = result[i] / 2;
        }
        return result;
    }
    //返回字符串
    public static String ArrayToString(int[] arr){
        if(arr == null){
            log.error("arr 为 null");
            return null;
        }
        StringBuilder s = new StringBuilder();
        for(int i = 0;i<3;i++){
            s.append(arr[i]+" ");
        }
        return s.toString();
    }
}

需要注意的点是:
  第一:市面上大多数表示MAX、Allocation、Need等都是使用二维数组,我这里因为需要记住进程名字所以我就使用Java的HashMap来表示这些数据结构。个人感觉HashMap来计算会舒服很多。
  第二:在系统安全性检查的时候,需要我们去遍历一个个满足条件的进程。我感觉用递归会很方便去解决这个问题,用循环的话太麻烦了/(ㄒoㄒ)/~~。
  总体就这样,有什么问题可以评论区留言,或者更好的看法。可以在评论区跟我探讨探讨。

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
银行家算法是一种最有代表性的避免死锁的算法,它可以确保系统分配资源的安全性。下面是用Java实现银行家算法的步骤: 1.定义数据结构:定义进程数、资源数、可利用资源向量Available、最大需求矩阵Max、分配矩阵Allocation和需求矩阵Need。 2.初始化数据:初始化Available、Max、Allocation和Need。 3.输入请求资源:输入请求资源的进程号和请求资源的数量。 4.判断请求是否合法:判断请求的数量是否小于等于该进程还需要的资源数量,以及请求的数量是否小于等于系统中可用的资源数量。 5.尝试分配资源:尝试分配资源,如果分配后系统仍然处于安全状态,则分配资源;否则,等待。 6.释放资源:进程完成任务后,释放已分配的资源。 下面是Java代码实现银行家算法的主要部分: ``` public class BankerAlgorithm { private int processNum; // 进程数 private int resourceNum; // 资源数 private int[] available; // 可利用资源向量 private int[][] max; // 最大需求矩阵 private int[][] allocation; // 分配矩阵 private int[][] need; // 需求矩阵 public BankerAlgorithm(int processNum, int resourceNum, int[] available, int[][] max, int[][] allocation) { this.processNum = processNum; this.resourceNum = resourceNum; this.available = available; this.max = max; this.allocation = allocation; this.need = new int[processNum][resourceNum]; for (int i = 0; i < processNum; i++) { for (int j = 0; j < resourceNum; j++) { need[i][j] = max[i][j] - allocation[i][j]; } } } // 判断是否处于安全状态 public boolean isSafe() { int[] work = new int[resourceNum]; boolean[] finish = new boolean[processNum]; for (int i = 0; i < resourceNum; i++) { work[i] = available[i]; } int count = 0; while (count < processNum) { boolean flag = false; for (int i = 0; i < processNum; i++) { if (!finish[i]) { boolean temp = true; for (int j = 0; j < resourceNum; j++) { if (need[i][j] > work[j]) { temp = false; break; } } if (temp) { for (int j = 0; j < resourceNum; j++) { work[j] += allocation[i][j]; } finish[i] = true; flag = true; count++; } } } if (!flag) { return false; } } return true; } // 尝试分配资源 public boolean tryAllocate(int process, int[] request) { for (int i = 0; i < resourceNum; i++) { if (request[i] > need[process][i] || request[i] > available[i]) { return false; } } for (int i = 0; i < resourceNum; i++) { available[i] -= request[i]; allocation[process][i] += request[i]; need[process][i] -= request[i]; } if (!isSafe()) { for (int i = 0; i < resourceNum; i++) { available[i] += request[i]; allocation[process][i] -= request[i]; need[process][i] += request[i]; } return false; } return true; } // 释放资源 public void release(int process, int[] release) { for (int i = 0; i < resourceNum; i++) { available[i] += release[i]; allocation[process][i] -= release[i]; need[process][i] += release[i]; } } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值