銀行家算法是用來避免死鎖的。
我自己的理解:我(銀行家)手裏有一筆資金,我現在要把這筆自己借出去,現在我需要保證,我以適當的順序去借出這筆存款,能保證我可以供給所有的借款者。即有一個安全序列(我借出去之後,它在有限時間內歸還給我,我就可以再次將這筆錢借給另外一個人。)
但是,如果我預測找不到這樣一個序列,也就是說,我不能同時滿足當前系統所有人的借款需求,即系統處於不安全的狀態!
首先我們定義幾個矩陣,矩陣功能見代碼
/**
* 系統資源種類數
* */
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