银行家算法是避免死锁的一种重要方法,采取的思路是预分配,尝试将资源分配给对应进程,然后判断新状态下是否状态安全,如果安全状态,则判断一下该对应进程是否满足执行的全部资源,如果满足,就回收掉该进程的资源,如果不满足则不作处理。如果是不安全状态,则进行状态的回退。
程序模块图
程序代码
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();
}
}
}
}
}
来源:CSDN
作者:孙靖俊
链接:https://blog.csdn.net/weixin_42220532/article/details/103860899