银行家算法是用来避免死锁的。
我自己的理解:我(银行家)手里有一笔资金,我现在要把这笔自己借出去,现在我需要保证,我以适当的顺序去借出这笔存款,能保证我可以供给所有的借款者。即有一个安全序列(我借出去之后,它在有限时间内归还给我,我就可以再次将这笔钱借给另外一个人。)
但是,如果我预测找不到这样一个序列,也就是说,我不能同时满足当前系统所有人的借款需求,即系统处于不安全的状态!
首先我们定义几个矩阵,矩阵功能见代码
/**
* 系统资源种类数
* */
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