银行家算法是用来避免死锁的。

我自己的理解:我(银行家)手里有一笔资金,我现在要把这笔自己借出去,现在我需要保证,我以适当的顺序去借出这笔存款,能保证我可以供给所有的借款者。即有一个安全序列(我借出去之后,它在有限时间内归还给我,我就可以再次将这笔钱借给另外一个人。)

但是,如果我预测找不到这样一个序列,也就是说,我不能同时满足当前系统所有人的借款需求,即系统处于不安全的状态!

 

首先我们定义几个矩阵,矩阵功能见代码

/**
     * 系统资源种类数
     * */
    private int sourceKinds;
    /**
     * 系统进程数目
     * */
    private int threadNums;

    /**
     * 初始资源数量
     * */
    private int source[];
    /**
     * 线程需要的最大资源数矩阵
     * */
    private int[][] MAX ;
    /**
     * 已分配给线程的资源矩阵
     * */
    private int[][] Allocation ;
    /**
     * 需求矩阵
     * */
    private int[][] Need;
    /**
     * 资源剩余矩阵
     * */
    private int[] Available;
    /**
     * 系统可提供给进程继续运行所需的各类资源数目
     * */
    private int[]Work;

然后我们就可以实现这个银行家算法了。

全部代码如下

package com.ly;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * Created by BorisLiu on 2019/10/21
 */
public class Banker {

    /**
     * 系统资源种类数
     * */
    private int sourceKinds;
    /**
     * 系统进程数目
     * */
    private int threadNums;

    /**
     * 初始资源数量
     * */
    private int source[];
    /**
     * 线程需要的最大资源数矩阵
     * */
    private int[][] MAX ;
    /**
     * 已分配给线程的资源矩阵
     * */
    private int[][] Allocation ;
    /**
     * 需求矩阵
     * */
    private int[][] Need;
    /**
     * 资源剩余矩阵
     * */
    private int[] Available;
    /**
     * 系统可提供给进程继续运行所需的各类资源数目
     * */
    private int[]Work;

    public Banker(int threadNums,int sourceKinds,int source[]){
        this.threadNums = threadNums;
        this.sourceKinds = sourceKinds;
        this.source = source;
        this.MAX = new int[threadNums][sourceKinds];
        this.Allocation = new int[threadNums][sourceKinds];
        this.Need = new int[threadNums][sourceKinds];
        for (int i = 0; i < threadNums; i++) {
           this.MAX[i] = new int[sourceKinds];
           this.Allocation[i] = new int[sourceKinds];
           this.Need[i] = new int[sourceKinds];
        }

        Available = new int[sourceKinds];
        Work = new int[sourceKinds];
    }
    /**
     * 设置进程需要最大资源数
     * */
    public void setMAX(){
        Scanner in = new Scanner(System.in);
        for (int i = 0; i < threadNums; i++) {
            System.out.println("请输入进程"+i+"最大需要的资源数目:");
            for (int j = 0; j < sourceKinds; j++) {
                System.out.println("请输入需要资源"+j+"的数目:");
                MAX[i][j] = in.nextInt();
            }
        }

//        for (int i = 0; i < threadNums; i++) {
//            for (int j = 0; j < sourceKinds; j++) {
//                System.out.print(MAX[i][j]+"==》");
//            }
//            System.out.println();
//        }
    }
    /**
     * 设置初始已分配资源
     * */
    public void setAllocation(){
        Scanner in = new Scanner(System.in);
        for (int i = 0; i < threadNums; i++) {
            System.out.println("请输入进程"+i+"初始已分配资源数目:");
            for (int j = 0; j < sourceKinds; j++) {
                System.out.println("请输入进程"+i+"初始已分类资源"+j+"的数目:");
                Allocation[i][j] = in.nextInt();
            }
        }
    }

    private void setNeed(){
        /**
         * 计算need矩阵
         * */
        for (int i = 0; i < threadNums; i++) {
            for (int j = 0; j < sourceKinds; j++) {
                Need[i][j] = MAX[i][j] - Allocation[i][j];
            }
        }
        /**
         * 计算剩余资源矩阵
         * */
        for (int i = 0; i < sourceKinds; i++) {
            int sum = 0;
            for (int j = 0; j < threadNums; j++) {
                sum+=Allocation[j][i];
            }
            Available[i] = source[i] - sum;
        }
    }

    /**
     * 找到一个安全序列
     * */
    private void findSafeSequence(){
        System.arraycopy(Available,0,Work,0,Available.length);

        int[] preWork = new int[Work.length];
        System.arraycopy(Available,0,preWork,0,Available.length);

        boolean Finish[] = new boolean[threadNums];
        List<String>  result = new ArrayList<String>();
        boolean flag = true;

        while(flag){
            boolean bool = false;
            for (int i = 0; i < threadNums; i++) {
                int count = 0;
                // 统计是否need【i】都 <= work[j]
                for (int j = 0; j < sourceKinds; j++ ) {
                    if (Need[i][j]<=Work[j]&&(!Finish[i])){
                        count++;
                    }
                }
                /**
                 * 如果need <= work
                 * */
                if (count == sourceKinds && (!Finish[i])){
                    for (int j = 0; j < sourceKinds; j++) {
                        Work[j] += Allocation[i][j];
                        Finish[i] = true;
                    }
                    result.add("P"+i);
                    bool = true;
                    break;
                }

            }
            if (bool){
                for (int i = 0; i < sourceKinds; i++) {
                    System.out.print("选择前work==>"+preWork[i]);
                    System.out.print("选择后work==>"+Work[i]);
                    System.out.println();
                }
                //更新preWork
                for (int i = 0; i < Work.length; i++) {
                    preWork[i] = Work[i];
                }

                flag = true;
            }else {
                flag = false;
            }

        }


        for (int i = 0; i < Available.length; i++) {
            System.out.print(Work[i]+"====");
        }
        System.out.println();

        if (result.size() == threadNums){
            System.out.println("找到安全序列!!!");
            result.forEach((e)->{
                System.out.println(e);
            });
        }else{
            System.out.println("没有找到安全序列!!!");
        }
    }

    public void print(){
        System.out.println("进程 Max Alloction Need Available ");
        for (int i = 0; i < threadNums; i++) {
            System.out.print("P"+i+" ");
            for (int j = 0; j < sourceKinds; j++) {
                System.out.print(MAX[i][j]+" |");
            }
            System.out.println();
        }
        for (int i = 0; i < threadNums; i++) {
            for (int j = 0; j < sourceKinds; j++) {
                System.out.print(Allocation[i][j]+" |");
            }
            System.out.println();
        }
        for (int i = 0; i < threadNums; i++) {
            for (int j = 0; j < sourceKinds; j++) {
                System.out.print(Need[i][j]+" |");
            }
            System.out.println();
        }

        for (int i = 0; i < sourceKinds; i++) {
            System.out.print(Available[i]+" ");
        }
        System.out.println("==>|");
    }


    public void initInput(){
        setMAX();
        setAllocation();
        setNeed();
        findSafeSequence();
    }


    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int threadNums = 0;
        int sourceNums = 0;
        int num = 0;
        System.out.println("请输入初始资源数:");
        num = in.nextInt();
        int[] source = new int[num];
        for (int i = 0; i < num; i++) {
            source[i] = in.nextInt();
        }
        System.out.println("请输入进程数==>");
        threadNums = in.nextInt();
        System.out.println("请输入资源种类数==>");
        sourceNums = in.nextInt();

        Banker banker = new Banker(threadNums,sourceNums,source);
        banker.initInput();

    }





}

 

输出结果:

请输入初始资源数:
3
10 8 7
请输入进程数==>
3
请输入资源种类数==>
3
请输入进程0最大需要的资源数目:
请输入需要资源0的数目:
8
请输入需要资源1的数目:
7
请输入需要资源2的数目:
5
请输入进程1最大需要的资源数目:
请输入需要资源0的数目:
5
请输入需要资源1的数目:
2
请输入需要资源2的数目:
5
请输入进程2最大需要的资源数目:
请输入需要资源0的数目:
6
请输入需要资源1的数目:
6
请输入需要资源2的数目:
2
请输入进程0初始已分配资源数目:
请输入进程0初始已分类资源0的数目:
3
请输入进程0初始已分类资源1的数目:
2
请输入进程0初始已分类资源2的数目:
0
请输入进程1初始已分配资源数目:
请输入进程1初始已分类资源0的数目:
2
请输入进程1初始已分类资源1的数目:
0
请输入进程1初始已分类资源2的数目:
2
请输入进程2初始已分配资源数目:
请输入进程2初始已分类资源0的数目:
1
请输入进程2初始已分类资源1的数目:
3
请输入进程2初始已分类资源2的数目:
2
选择前work==>4选择后work==>6
选择前work==>3选择后work==>3
选择前work==>3选择后work==>5
选择前work==>6选择后work==>7
选择前work==>3选择后work==>6
选择前work==>5选择后work==>7
选择前work==>7选择后work==>10
选择前work==>6选择后work==>8
选择前work==>7选择后work==>7
10====8====7====
找到安全序列!!!
P1
P2
P0