银行家算法(Java实现)

99封情书 提交于 2020-01-06 19:04:44

  银行家算法是避免死锁的一种重要方法,采取的思路是预分配,尝试将资源分配给对应进程,然后判断新状态下是否状态安全,如果安全状态,则判断一下该对应进程是否满足执行的全部资源,如果满足,就回收掉该进程的资源,如果不满足则不作处理。如果是不安全状态,则进行状态的回退。

在这里插入图片描述

程序模块图

在这里插入图片描述

程序代码

Bank类:


import java.util.*;

/**
 *
 */
public class Bank {
    /**
     * 资源可用数目
     */
    private int[] Available;
    /**
     * 最大需求矩阵
     */
    private int[][] Max;
    /**
     * 已分配矩阵
     */
    private int[][] Alloction;
    /**
     * 需求矩阵
     */
    private int[][] Need;
    /**
     * 进程是否完成矩阵
     */
    private boolean[] Finish;
    /**
     * 进程数组
     */
    private Process[] Processes;

    /**
     * 安全状态进程
     */
    private List<Process> securityProcesses;

    /**
     * 进程请求资源数组
     */
    private int[] request;

    private boolean[] tmp;


    /**
     * 无参构造,需调用初始化函数
     */
    public Bank() {
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        Scanner scanner = new Scanner(System.in);
        //进程初始化,Finish矩阵初始化
        System.out.println("请输入进程个数:");
        int processNum = scanner.nextInt();
        Finish = new boolean[processNum];
        Processes = new Process[processNum];
        System.out.println("请按顺序输入各进程的名称:");
        for (int i = 0; i < Processes.length; i++) {
            String tmpProcessName = scanner.next();
            Processes[i] = new Process(tmpProcessName);
        }

        //资源初始化 Avalibale数组,Allocation矩阵,Max矩阵,Need矩阵
        System.out.println("请输入资源种类数:");
        int resourecNum = scanner.nextInt();
        System.out.println("请输入Avaliable数组:");
        Available = new int[resourecNum];
        for (int i = 0; i < resourecNum; i++) {
            Available[i] = scanner.nextInt();
        }
        System.out.println("请输入Allocation矩阵");
        Alloction = new int[processNum][resourecNum];
        for (int i = 0; i < processNum; i++) {
            for (int j = 0; j < resourecNum; j++) {
                Alloction[i][j] = scanner.nextInt();
            }
        }
        System.out.println("请输入Max矩阵");
        Max = new int[processNum][resourecNum];
        for (int i = 0; i < processNum; i++) {
            for (int j = 0; j < resourecNum; j++) {
                Max[i][j] = scanner.nextInt();
            }
        }
        Need = new int[processNum][resourecNum];
        for (int i = 0; i < processNum; i++) {
            for (int j = 0; j < resourecNum; j++) {
                Need[i][j] = Max[i][j] - Alloction[i][j];
            }
        }
        securityProcesses = new ArrayList<>(Finish.length);
        request = new int[Available.length];
        Finish = new boolean[Finish.length];
        tmp = new boolean[Finish.length];
        System.out.println();
    }

    /** p2 1 2 p2 0 1 p0 3 1
     * 安全性检测
     */
    public boolean securityExamine() {
        /**
         * 工作矩阵,其实就是Avaliable
         */
        int[] Work = new int[Available.length];
        System.arraycopy(Available,0,Work,0, Available.length);

//        scanfNoNeed(Work);
        for (int i = 0; i<Processes.length ;i++) {
            if(!Finish[i]) {
                boolean tmp = true;
                for (int j = 0; j < Work.length; j++) {
                     if(Need[i][j]>Work[j]) {
                        tmp = false;
                        break;
                    }
                }
                if(tmp) {
                    //满足条件,表示i号进程满足可以分配的情况
                    String processName = null;
                    try {
                        processName = getProcessName(i);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    //修改i进程的状态位
                    Finish[i] = true;
                    //回收i进程占有的资源
                    for (int j = 0; j < Work.length; j++) {
                        Work[j] = Work[j] + Alloction[i][j];
                    }
                    //把该进程放入安全序列中
                    securityProcesses.add(Processes[i]);
                    //每次从头开始查找是否可以分配
                    i = -1;
                    System.out.println("进程"+processName+"分配成功!     此时Work:"+Arrays.toString(Work));
                }
            }
        }
        //全部分配完直接返回
        if(securityProcesses.size() == Finish.length) {
            System.out.println("状态安全");
            System.out.println("安全序列为:"+ securityProcesses);
            securityProcesses.clear();
            Finish = new boolean[Finish.length];
            return true;
        }
        //状态不安全
        System.out.println("状态不安全");
        return false;
    }

    /**
     * 扫描need矩阵,将need全为0的进程优先放入安全序列
     */
    private void scanfNoNeed(int[] Work) {
        for (int i = 0; i < Finish.length; i++) {
            boolean isNeed = true;
            for (int j = 0; j < Work.length; j++) {
                if(Need[i][j] != 0) {
                    isNeed = false;
                    break;
                }
            }
            //满足条件,则i进程need全为0
            if(isNeed && (!tmp[i])) {
                String processName = null;
                try {
                    processName = getProcessName(i);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                //修改i进程的状态位
                Finish[i] = true;
                //回收i进程占有的资源
                for (int j = 0; j < Work.length; j++) {
                    Work[j] = Work[j] + Alloction[i][j];
                }
                //把该进程放入安全序列中
                securityProcesses.add(Processes[i]);
                tmp[i] = true;
                System.out.println("进程"+processName+" need为0,直接释放!     此时Work:"+Arrays.toString(Work));
            }
        }
    }

    /**
     * 请求资源
     */
    public void request() {
        //输入
        System.out.println("请输入请求资源的进程名称:");
        Scanner scanner = new Scanner(System.in);
        String processName = scanner.nextLine();
        int processNum = 0;
        try {
            processNum = getProceesNum(processName);
        } catch (IllegalAccessException e) {
            System.out.println("进程名称错误,找不到对应进程");
            return;
        }
        System.out.println("请分别输入各进程的请求资源数目:");
        for (int i = 0; i < request.length; i++) {
            request[i] = scanner.nextInt();
        }

        //request<=work
        for (int i = 0; i < request.length; i++) {
            if(request[i] > Available[i]) {
                System.out.println("request > avaliable,请求过大,无法分配");
                return;
            }
        }

        //request<=need
        for (int i = 0; i < request.length; i++) {
            if(request[i] > Need[processNum][i]) {
                System.out.println("request > need,请求参数不合法");
                return;
            }
        }
        //为该进程分配资源
        for (int i = 0; i < request.length; i++) {
            Need[processNum][i] -= request[i];
            Available[i] -= request[i];
            Alloction[processNum][i] += request[i];
        }

        /**
         * 分配完成后,判断该状态是否安全,如果不安全,进行回退
         */
        boolean isSecurity = securityExamine();
        if(!isSecurity) {
            //进程回退
            for (int i = 0; i < request.length; i++) {
                Need[processNum][i] += request[i];
                Available[i] += request[i];
                Alloction[processNum][i] -= request[i];
            }
        } else {
            scanfNoNeed(Available);
            printState();
        }
    }

    public void printState() {
        System.out.println();
        System.out.println("-------------------------当前进程状态----------------------------");
        System.out.println();
        System.out.println("processes\t\tAllocation\t\tNeed\t\t");
        for (int i = 0; i < Finish.length; i++) {
            String processName = null;
            try {
                processName = getProcessName(i);
            } catch (IllegalAccessException e) {
                System.out.println("非法的下标");
            }
            System.out.print(processName+"\t\t\t\t");
            for (int j = 0; j < Available.length; j++) {
                System.out.print(Alloction[i][j]+" ");
            }
            System.out.print("\t\t");
            for (int j = 0; j < Available.length; j++) {
                System.out.print(Need[i][j]+" ");
            }
            System.out.println();
        }
        System.out.println("Avalibale:"+Arrays.toString(Available));
    }

    private String getProcessName(int i) throws IllegalAccessException {
        for (int j = 0; j < Processes.length; j++) {
            if(i == j) {
                return Processes[i].getName();
            }
        }
        throw new IllegalAccessException("非法下标");
    }

    /**
     * 根据进程名称找到对应的第几个进程
     * @param processName 进程名称
     * @return 返回第几个进程
     * @throws IllegalAccessException 非法的名称异常
     */
    private int getProceesNum(String processName) throws IllegalAccessException {
        for (int i = 0; i < Processes.length; i++) {
            if(processName.equals(Processes[i].getName())) {
                return i;
            }
        }
        throw new IllegalAccessException("名字非法");
    }
}

Process类


/**
 *  进程类,主要是用来标记进程的名称,进程的其他属性(need,allocation等)都在Bank的矩阵中包含
 */
class Process {

    /**
     * 进程名称
     */
    private String name;

    /**
     *
     * @param name 进程名称
     */
    public Process(String name) {
        this.name = name;
    }

    /**
     * get方法
     * @return 返回对应进程的名称
     */
    public String getName() {
        return name;
    }

    /**
     * 设置进程名称
     * @param name 传入对应进程的名称进行设置操作
     */
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Process{" +
                "name='" + name + '\'' +
                '}';
    }
}

测试类:


import java.util.Scanner;

/**
 *
 */
public class Main {
    public static void main(String[] args) {
        Bank bank = new Bank();
        Scanner scanner = new Scanner(System.in);
        while (true){
            System.out.println();
            System.out.println("请输入选择:1.安全性检测  2.银行家算法  3.打印进程状态  4.退出");
            int select = scanner.nextInt();
            if(select == 1) {
                bank.securityExamine();
            } else if(select == 2) {
                bank.request();
            } else if(select == 3) {
                bank.printState();
            } else if(select == 4){
                break;
            }else {
                try {
                    throw new IllegalAccessException("输入异常");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!