实验需求
(1) 输入的形式和输入值的范围;
输入进程数量,资源种类数,资源总数目,进程需要的各资源的最大数量,进程当前状态各资源的分配情况。根据输入的资源总数目、进程对各类资源的需求最大数、当前状态的各类资源对各进程的分配情况,可得当前状态各进程对各类资源的需求情况和当前状态各类资源的剩余数目。以上各类数据都以整型数组形式存在
(2) 输出的形式;
如果需要知晓当前资源分配情况时,将相应内容在屏幕上输出即可,由于是数组,只需利用循环来达到将全部信息输出的目的
(3) 程序所能达到的功能。
判断当前的资源分配情况是不是安全状态。这里的当前资源分配情况可以是初始各项资源都已分配好的状态,也可以是有进程请求资源,进程的请求可被满足而更新的资源分配情况。对当前资源分配情况尝试找出一个安全序列以证明当前状态是否安全。若能找到一个安全序列,则当前状态安全,否则,状态不安全,并恢复到安全状态时的资源分配情况。
概要设计
1、 数据结构 :不把各属性附属在进程上,而是把进程和资源作为属性,所以采用简单的整型的数组
2、 程序模块 :采用java语言定义了两个类bankerTest和banker,其中bankerTest为主类。Banker类中有定义表示进程和各类资源数组,采用变长数组且长度由键盘输入,初始化数组,银行家算法,安全性算法
3、 各模块之间的调用关系:主类先创建banker类对象,调用banker类中的方法,输入进程数量,资源种类数,各进程对各资源的最大需求量,初态各进程已分配资源情况,其他资源情况可由以上资源情况得出,判断当前状态是否安全,已般初始测试用例状态建议是个安全状态,接着进入主函数的循环,有进程请求资源,则调用银行家算法后根据情况选择是否调用安全性算法,若产生了安全序列,则输出相应信息,不能产生安全序列,则回复到对应请求资源前的资源分配状态,再次判断是否有进程请求资源,以此循环,直到没有进程请求资源,跳出主函数循环,程序执行结束。
代码内容
import java.util.Scanner;
class banker{
int m,n;
int all_Resourse[];//初始各类资源总数
int Max[][];
int Allocation[][];
int Need[][];
int Available[];
int Request[][];
int Work[] ;
boolean Finish[];
Scanner in=new Scanner(System.in);
int num=0;//设置全局变量用于请求资源时的进程编号
public void set() {
System.out.println("输入进程个数:");
Scanner Inm=new Scanner(System.in);
this.m=Inm.nextInt();
System.out.println("输入资源种数:");
Scanner Inn=new Scanner(System.in);
this.n=Inn.nextInt();
all_Resourse=new int[n];
Request= new int[m][n];
Work = new int[n];//给定数组长度
for(int j=0;j<n;j++) {
System.out.println("输入资源"+j+"总数目:");
Scanner Inj=new Scanner(System.in);
all_Resourse[j]=Inj.nextInt();
}
}
public void arrSet() {
Max=new int[m][n];
Allocation=new int[m][n];
Need=new int[m][n];
Finish=new boolean[m];
Available=new int[n];
for(int i=0;i<m;i++) {
System.out.println("输入P"+i+"进程所需各类资源的最大数("+n+"位数");
for(int j=0;j<n;j++) {
Scanner In=new Scanner(System.in);
Max[i][j]=In.nextInt();
}
}//初始化Max数组
for(int i=0;i<m;i++) {
System.out.println("输入P"+i+"进程已分配各类资源的数目("+n+"位数");
for(int j=0;j<n;j++) {
Scanner In=new Scanner(System.in);
Allocation[i][j]=In.nextInt();
}
}//初始化Allocation数组
for(int i=0;i<m;i++) {
for(int j=0;j<n;j++) {
Need[i][j]=Max[i][j]-Allocation[i][j];
}
}//初始化Need数组
int sum_Allocation[]=new int[n];
for(int j=0;j<n;j++) {
for(int i=0;i<m;i++) {
sum_Allocation[j]+=Allocation[i][j];
}
}
for(int j=0;j<n;j++) {
Available[j]=all_Resourse[j]-sum_Allocation[j];
}//初始化Available数组
}
public void printSystemdata(){
System.out.println("此时资源分配量如下:");
System.out.println("进程 "+" Max "+" Alloction "+" Need "+" Available ");
for(int i=0;i<m;i++){
System.out.print("P"+i+"| ");
for(int j=0;j<n;j++){
System.out.print(Max[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<n;j++){
System.out.print(Allocation[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<n;j++){
System.out.print(Need[i][j]+" ");
}
System.out.print("| ");
if(i==0){
for(int j=0;j<n;j++){
System.out.print(Available[j]+" ");
}
}
System.out.println();
}
}
public void setRequest() {//设置请求资源量Request
System.out.println("输入请求资源的进程编号(0~"+(m-1)+"):");
num= in.nextInt();//设置全局变量进程编号num
for (int j=0;j<n; j++) {
System.out.println("输入请求资源"+j+"的数量:");
Request[num][j] = in.nextInt();
}
System.out.print("进程P" + num + "对各资源请求Request:");
for(int j=0;j<n;j++) {
System.out.print(Request[num][j]) ;
}
System.out.println();
BankerAlgorithm();
}
public void BankerAlgorithm() {//银行家算法
boolean T=false;//对请求进程是否实行尝试分配
int j;
for( j=0;j<n;j++) {
if (Request[num][j] <= Need[num][j]&&Request[num][j]<=Available[j] ) {}
else
break;
}//检查进程请求的各个资源是否小于各资源现有数目和对应进程的需求量数目
if(j==n) {
T=true;
for (int i=0;i<n; i++) {
Available[i] -= Request[num][i];
Allocation[num][i] += Request[num][i];
Need[num][i] -= Request[num][i];
}
}//满足分配条件
else {
System.out.println("无足够的资源可分配或请求超出需求量,不予分配");
}//不满足分配条件
if(T==true){//请求资源可分配
System.out.println("可分配");
printSystemdata();
System.out.println("进入安全算法");
SecurityAlgorithm();//检测请求资源分配后是否存在安全序列
}
}
public void SecurityAlgorithm() {//安全算法
for(int j=0;j<n;j++) {
Work[j]=Available[j];
}//初始化Work数组
int[] S=new int[m];//安全序列
boolean flag = true;
int count = 0;
int r,i=0;
int p=0,j;
int CirCleNum=0;//进程循环次数
for(i=0;i<m;i++) {
Finish[i]=false;
}//将Finish 数组全部置为false
i=0;
if(flag){
System.out.println("进程 "+" Work "+" Alloction "+" Need "+" Work+Alloction ");
flag = false;
}
while(count<m&&CirCleNum<20) {
if (Finish[i]==false) {
for(j=0;j<n;j++) {
if(Need[i][j]<=Work[j]) {
p++;
}
}
if(p==n) {//找到满足要求的一个进程i
Finish[i]=true;
S[count]=i;//将对应进程号放入数组
System.out.print("P"+i+" |");
for (j =0; j< n; j++){
System.out.print(Work[j]+" ");
}
System.out.print(" | ");
for(j=0;j<n;j++){
System.out.print(Allocation[i][j]+" ");
}
System.out.print(" | ");
for(j=0;j<n;j++){
System.out.print(Need[i][j]+" ");
}
System.out.print(" | ");
for (j=0;j<n;j++){
Work[j]+=Allocation[i][j];
System.out.print(Work[j]+" ");
}
System.out.println();
count++;//分配进程数加1
}//显示信息并更新work数组
if(i<m-1) {
i++;
}//没有来到最后一个进程,跳过,检查下一个进程
else {
CirCleNum++;//从最后一个进程到第一个进程,实现循环
i=0;
}
}//对未放入安全序列的进程(Finish[i]=false)的进程检查 且两种方式中的一种跳转到下一个进程
else {
if(i<m-1) {
i++;
}//未来到最后一个进程,跳过,检查下一个进程
else {
CirCleNum++;//从最后一个进程到第一个进程
i=0;
}
}//已放入安全序列的进程以两种方式中的一种跳转到下一个进程
p=0;//重新置零,给下一个进程使用
}
if(count==m){//循环跳出是因为安全序列中的个数已等于进程总数
System.out.print("此时存在一个安全序列:");
for ( i=0;i<m;i++){//输出安全序列
System.out.print("P"+S[i]+" ");
}
System.out.println("当前可分配!");
}
if(count<m){//循环跳出是因为循环有限且足够多次数已结束
System.out.println("当前系统处于不安全状态,不存在安全序列。");
for (i=0;i<n; i++) {
Available[i] += Request[num][i];
Allocation[num][i] -= Request[num][i];
Need[num][i] += Request[num][i];
}//尝试分配失败,恢复原态
}
}
}
public class bankerTest {
public static void main(String args[]) {
banker a=new banker();
a.set();//进程数、资源种类、各类资源总数目
a.arrSet();
a.printSystemdata();
a.SecurityAlgorithm();
System.out.println("有进程请求资源?true/false");
Scanner In=new Scanner(System.in);
Boolean t=In.nextBoolean();
while(t==true) {
a.setRequest();
System.out.println("有进程请求资源?true/false");
boolean y=In.nextBoolean();
if(y==false)
t=false;
}
}
}
实验总结
过程中所遇到的问题:有数组下标越界,数组如果已经给定了大小,那么下标就只能从零到数组长度减一;怎么样才能将进程请求的各项资源逐一与现有资源数目和进程的各项资源的数目作对比,只要有一个对比不符合,该进程就不满足分配资源的条件?在请求资源算法中定义了一个初值为0的整型变量并且采用for循环,对每一种资源都检查他们是否同时满足现有的资源和需求的资源都大于请求的资源,若满足,则给整型变量加一,表示该资源可以分配,依次检查其他资源是否可被分配。最终如果整型变量的值与资源种类数相等,则所有资源都可被分配,此时进程请求的资源才能被满足;当试图生成安全序列,检查到下标靠后的进程而前面的进程还未被放入安全序列,如果下标靠后的进程先放入未来可能被叫做安全序列的序列,释放资源后可使下标靠前的进程满足条件而被放入未来可能被叫做安全序列的序列,怎么样才能在检查完了下标靠后的进程后又能去检查下标靠前的进程?初始采用的是递归,递归的内容是从下标为零开始检查各进程,最终考虑到需要参数及返回值问题较为复杂,采用if-else语句,不论检查的进程能不能放入安全序列,只要该进程是最后一个进程,就赋值进程下标为0,使下一次从第一个进程开始检查,同时还需设置有限多的循环次数,作为进程回转避免死循环的终止条件。