操作系统 银行家算法 Java 实现
目录:
- 银行家算法的基本原理
- 代码实现
- 测试结果截图
1. 银行家算法的基本原理
2. 代码实现
1). 资源分配表类 (SrcAllocTable) 与进程记录类 (Record)
public class SrcAllocTable {
private int processNum;
private int sourceNum;
private Record[] table;
private int[] sum;
private int[] available;
public SrcAllocTable(int[] sum, Record[] table) {
// if(sum.length != table.length)
// throw XXXException;
this.sum = sum;
this.table = table;
this.processNum = table.length;
this.sourceNum = sum.length;
this.available = sum.clone();
for(int i = 0; i<sourceNum; i++)
for(int j = 0; j<processNum; j++)
available[i] -= table[j].getAllocation()[i];
}
public SrcAllocTable(SrcAllocTable table){
this.processNum = table.getProcessNum();
this.table = table.getTable().clone();
this.sum = table.getSum().clone();
this.available = table.getAvailable();
}
public Record[] getTable() {
return table;
}
public int[] getAvailable() {
return available;
}
public int[] getSum() {
return sum;
}
public int getProcessNum() {
return processNum;
}
public int getSourceNum() {
return sourceNum;
}
@Override
public String toString() {
StringBuilder info = new StringBuilder();
for(int i = 0; i<processNum; i++)
info.append(table[i].toString()).append("\n");
info.append("Available: ").append(Arrays.toString(available));
return info.toString();
}
}
class Record{
private String proName;
private int sourceNum;
private int[] max;
private int[] allocation;
private int[] need;
private boolean isFinished;
public Record(String proName, int[] max, int[] allocation) {
this.proName = proName;
this.sourceNum = max.length;
this.max = max;
this.allocation = allocation;
this.need = new int[sourceNum];
for(int i = 0; i<sourceNum; i++)
need[i] = max[i] - allocation[i];
this.isFinished = false;
}
public int[] getAllocation() {
return allocation;
}
public int[] getNeed() {
return need;
}
public int getSourceNum() {
return sourceNum;
}
public String getProName() {
return proName;
}
public boolean isFinished() {
return isFinished;
}
public void setFinished(boolean finished) {
isFinished = finished;
}
@Override
public String toString() {
return proName + " "
+ "Max: " + Arrays.toString(max) + " "
+ "Allocation: " + Arrays.toString(allocation) + " "
+ "Need: " + Arrays.toString(need) + " "
+ "IsFinished: " + isFinished;
}
// 测试
public static void main(String[] args){
int[] max0 = {7, 5, 3};
int[] allocation0 = {0, 1, 0};
Record r0 = new Record("p0", max0, allocation0);
int[] max1 = {3, 2, 2};
int[] allocation1 = {2, 0, 0};
Record r1 = new Record("p1", max1, allocation1);
int[] max2 = {9, 0, 2};
int[] allocation2 = {3, 0, 2};
Record r2 = new Record("p2", max2, allocation2);
Record[] table = {r0, r1, r2};
int[] sum = {10, 5, 7};
SrcAllocTable st = new SrcAllocTable(sum, table);
System.out.println(st);
}
}
2). 银行家类(实现银行家算法)
public class Banker {
private SrcAllocTable srcTable;
public Banker(SrcAllocTable table) {
this.srcTable = table;
}
/**
* 安全性检测
* @param i 进程记录的编号
* @param request 请求的资源数组
* @return 是否安全
*/
public boolean securityDetect(int i, int[] request) {
boolean isSecurity = false;
// 先复制整张资源分配表
SrcAllocTable tmpTable = new SrcAllocTable(srcTable);
showDebugInfo("Before allocation: ", tmpTable);
// 1. 试探性分配资源
Record[] table = tmpTable.getTable();
int[] need = table[i].getNeed();
int[] available = tmpTable.getAvailable();
int[] allocated = table[i].getAllocation();
for (int k = 0; k < request.length; k++) {
need[k] -= request[k];
available[k] -= request[k];
allocated[k] += request[k];
}
showDebugInfo("After allocation: ", tmpTable);
int procCount = 0;
StringBuilder procQueue = new StringBuilder();
int procNum = tmpTable.getProcessNum(); // 尚未完成的进程或者说表中 isFinished 为 false 的记录的数量
int srcNum = tmpTable.getSourceNum(); // 资源种类数
for(int n = 0; n<procNum; n++) {
for (int k = 0; k < procNum; k++) { // 外层循环遍历资源表中的各个进程记录
int count = 0;
if(table[k].isFinished())
continue;
for (int j = 0; j < srcNum; j++) // 对每个进程的资源进行判断
if (table[k].getNeed()[j] <= available[j])
count++;
if (count == srcNum) { // 如果进程的 need 比 available 要少那么就是可以完成的
table[k].setFinished(true);
for (int j = 0; j < srcNum; j++) {
table[k].getNeed()[j] = 0;
available[j] += table[k].getAllocation()[j];
table[k].getAllocation()[j] = 0;
}
procQueue.append(table[k].getProName() + " ");
procCount++;
showDebugInfo("Security Detection: ", tmpTable);
}
}
}
showDebugInfo("Security Detection Result: ", tmpTable);
System.out.println("Security Queue: " + procQueue.toString());
if(procNum == procCount)
isSecurity = true;
else
System.out.println("The request of source can't pass the security detection");
return isSecurity;
}
/**
* 是否可为进程分配所请求的资源
* 检测步骤:
* 1. request i <= need i ?
* 2. request i <= available ?
* 3. 是否可以通过安全性检测
* @param i 进程记录编号
* @param request 请求分配的资源
* @return 是否可以为请求进程分配资源
*/
public boolean ifAllocate(int i, int[] request) {
// 1. request <= need
// 2. request <= available
int[] need = srcTable.getTable()[i].getNeed();
int[] available = srcTable.getAvailable();
for (int k = 0; k < request.length; k++)
if (request[k] > need[k] || request[k] > available[k]) {
System.out.println("Sorry, the requested source may out of needed or available source!");
return false;
}
// 3. security Detect
return securityDetect(i, request);
}
// 打印资源分配表的情况
public void showDebugInfo(String info, SrcAllocTable tmpTable){
System.out.println(info);
System.out.println(tmpTable);
System.out.println("------------------------------------------");
}
public static void main(String[] args) {
int[] max0 = {7, 5, 3};
int[] allocation0 = {0, 1, 0};
Record r0 = new Record("p0", max0, allocation0);
int[] max1 = {3, 2, 2};
int[] allocation1 = {2, 0, 0};
Record r1 = new Record("p1", max1, allocation1);
int[] max2 = {9, 0, 2};
int[] allocation2 = {3, 0, 2};
Record r2 = new Record("p2", max2, allocation2);
int[] max3 = {2, 2, 2};
int[] allocation3 = {2, 1, 1};
Record r3 = new Record("p3", max3, allocation3);
int[] max4 = {4, 3, 3};
int[] allocation4 = {0, 0, 2};
Record r4 = new Record("p4", max4, allocation4);
Record[] table = {r0, r1, r2, r3, r4};
int[] sum = {10, 5, 7};
SrcAllocTable st = new SrcAllocTable(sum, table);
System.out.println(st);
// Banker
Banker banker = new Banker(st);
int i = 1;
int[] request = {1, 0, 2};
System.out.println(banker.ifAllocate(i, request));
}
}
3. 测试结果: