共享资源分配与银行家算法
大家好!我是小笙,最近一周我们进行课程设计的制作,以下是我分享的源码!
课程设计的要求
此次课程设计的主要内容是模拟实现资源分配。同时要求编写和调试一个系统动态分配资源的简单模拟程序,观察死锁产生的条件,并使用适当的算法,有效的防止和避免死锁的发生。
具体用银行家算法实现资源分配。
要求如下:
1.设计一个5个并发进程共享3类不同资源的系统,进程可动态地申请资源和释放资源,系统按各进程的申请动态地分配资源。(也可以超过5个进程,3类资源)
2.设计用银行家算法和随机分配算法,实现资源分配的两个资源分配程序,应具有显示或打印各进程依次要求申请的资源数以及依次分配资源的情况。
3.确定一组各进程依次申请资源数的序列,在相同的情况下分别运行上述两种资源分配程序,观察运行结果。
笙式解读(代码实现):
1.可以手动一个一个进程的方式输入资源,进程数以及资源种类数都是可以我们自己设置
2.分别实现银行家算法和随机分配算法
银行家算法的分配资源是:当某个进程提出资源申请时,假定先分配资源给它,然后查找各进程的剩余请求,检查系统剩余资源量是否由于进程的分配而导致系统死锁。若能,则让进程等待,否则,让进程的假分配变为真分配。
随机分配算法的分配原则:当进程申请资源时,如果进程现有资源数能满足进程的当前申请量,就把资源分配给进程,否则,让其等待。这样,随机算法可能引起死锁。
3.安全性算法的实现输出序列
主菜单
// 启动类
public class Application {
public static void main(String[] args) throws IOException {
new CoreProcessor();
}
}
主菜单运行效果
// 主菜单的代码
public CoreProcessor() throws IOException {
while(true){
System.out.println("*******************************");
System.out.println(" 共享资源分配与银行家算法 ");
System.out.println(" 1.系统资源分配信息 ");
System.out.println(" 2.添加进程及进程信息 ");
System.out.println(" 3.删除进程及进程信息 ");
System.out.println(" 4.查找进程及进程信息 ");
System.out.println(" 5.检查是否序列安全 ");
System.out.println(" 6.提出请求资源 ");
System.out.println(" 7.读入文件数据 ");
System.out.println(" 8.保存文件数据 ");
System.out.println(" 9.清除进程和资源信息 ");
System.out.println(" 10.退出系统 ");
System.out.println("*******************************");
System.out.print("输入序号(1~10):");
// 序号必须在1~10之间
int choice = new Scanner(System.in).nextInt();
if(!(choice <=10 && choice>=1)){
continue;
}
switch (choice){
case 1: SystemResourceInformation();
break;
case 2: AddProcessesAndProcessInformation();
break;
case 3: DeleteProcessesAndProcessInformation();
break;
case 4: SearchForProcessesAndProcessInformation(head);
break;
case 5: IsSafety();
break;
case 6: AskForRequest();
break;
case 7: ReadFile();
break;
case 8: SaveFile();
break;
case 9: ClearProcessAndResourceInformation();
break;
case 10: ExitSystem();
break;
default:
System.out.println("impossible");
}
}
}
主要函数说明
添加进程
笙式说明:
我实现两种添加进程的方式
1.手动一个进程一个进程输入(麻烦)
2.直接文件读入(方便快捷)
1.手动输入进程
做任何操作前,我们都需要先完成系统资源信息录入
录入内容为:系统资源种类数 && 可分配资源数(available)
如果我们输入错误如何更改呢?
我们可以通过主菜单的9序号清空系统资源数据
// 9.清除进程和资源信息
private void ClearProcessAndResourceInformation(){
numberOfResourcTypes = 0;
head.next = null;
}
接下类就是CRUD的操作,不需要我多说叭!
我操作一下添加进程
// 2.添加进程及进程信息
private void AddProcessesAndProcessInformation(){
if(numberOfResourcTypes == 0){
System.out.println("系统资源分配信息未输入!!!");
SystemResourceInformation();
}
while (true){
System.out.println("*******************************");
System.out.println(" 添加进程及进程信息 ");
System.out.println(" 1.添加进程 ");
System.out.println(" 2.退出 ");
System.out.print("输入序号(1~2):");
// 序号必须在1~2之间
int choice = new Scanner(System.in).nextInt();
if(choice == 2){
System.out.println("添加进程完成!");
System.out.println("*******************************");
return;
}
if(!(choice <=2 && choice>=1)){
System.out.println("*******************************");
continue;
}
// 开始添加进程信息
// processName
System.out.print("\n输入进程名:");
String processName = new Scanner(System.in).next().trim();
// Max
System.out.print("输入"+numberOfResourcTypes+"个最大需求资源数(max):");
int[] max = new int[numberOfResourcTypes];
Scanner sc = new Scanner(System.in);
for (int i = 0; i < max.length; i++) {
max[i] = sc.nextInt();
}
// Allocation Need
System.out.print("输入"+numberOfResourcTypes+"个已分配资源数(allocation):");
int[] allocation = new int[numberOfResourcTypes];
int[] need = new int[numberOfResourcTypes];
for (int i = 0; i < numberOfResourcTypes; i++) {
allocation[i] = sc.nextInt();
need[i] = max[i] - allocation[i];
}
// 检验是否出错 及其进程名有无重复
if(IsSameName(processName)){
System.out.println("进程名重复了,请重新输入");
continue;
}
for (int i = 0; i < numberOfResourcTypes; i++) {
if(max[i]<0 || allocation[i]<0 || need[i]<0){
System.out.println("进程数据有误,返回核心处理器!!!");
return;
}
}
// 添加新进程到新链表
Process temp = head;
// 遍历链表,找到最后
while(true){
if(temp.next == null){
break;
}
temp = temp.next;
}
// 当退出while循环时候,temp就指向最后一个节点
temp.next = new Process(processName,max,allocation,need);
// 提示进程是否安全
// IsSafety();
System.out.println();
System.out.println("*******************************");
}
}
既然添加了两个进程,此时我想看看这两个进程了怎么办?放心没问题
2.直接文件读入
读入的文本说明
读入的实现效果
读入的代码实现
// 7.读入文件数据
public void ReadFile() {
if(numberOfResourcTypes != 0){
System.out.println("系统资源分配信息已经输入!!!");
return;
}
List input = new ArrayList();
System.out.println("请问你要读入文件的文件名:");
String s = new Scanner(System.in).next();
String pathname = "E:\\enableCleanProject\\SharedResourceAllocationAndBankerAlgorithm\\OSAlgorithm\\src\\" + s;
try (FileReader reader = new FileReader(pathname);BufferedReader br = new BufferedReader(reader)) {
String line;
while ((line = br.readLine()) != null) {
// 一次读入一行数据
String[] str =line.split(" ");
input.add(str[0]);
}
} catch (IOException e) {
e.printStackTrace();
}
numberOfResourcTypes = Integer.valueOf(input.get(0).toString());
String processName = "";
Available = new int[numberOfResourcTypes];
for (int i = 1; i <= numberOfResourcTypes; i++) {
Available[i-1] = Integer.valueOf(input.get(i).toString());
}
int count = (input.size()-(1+numberOfResourcTypes))/(numberOfResourcTypes*3+1);
int[][] max = new int[count][numberOfResourcTypes];
int[][] allocation = new int[count][numberOfResourcTypes];
int[][] need = new int[count][numberOfResourcTypes];
// 添加新进程到新链表
Process temp = head;
while(count > 0){
processName = input.get((1+numberOfResourcTypes)+(5-count)*(numberOfResourcTypes*3+1)).toString();
int num =(1+numberOfResourcTypes)+(5-count)*(numberOfResourcTypes*3+1);
int index = 0;
for (int i = num+1; i <= num+numberOfResourcTypes; i++) {
max[5-count][index] = Integer.valueOf(input.get(i).toString());
index++;
}
index = 0;
for (int i = num+1+numberOfResourcTypes; i <= num+numberOfResourcTypes*2; i++) {
allocation[5-count][index] = Integer.valueOf(input.get(i).toString());
index++;
}
index = 0;
for (int i = num+1+numberOfResourcTypes*2; i <= num+numberOfResourcTypes*3; i++) {
need[5-count][index] = Integer.valueOf(input.get(i).toString());
index++;
}
temp.next = new Process(processName,max[5-count],allocation[5-count],need[5-count]);
temp = temp.next;
count--;
}
System.out.println("读入成功");
}
好啦!结束了进程录入,上主角三种算法:安全性算法,银行家算法,随机分配算法
算法实现
安全性算法
// 5.检查是否序列安全
private boolean IsSafety(){
if(numberOfResourcTypes == 0){
System.out.println("系统资源分配信息未输入!!!");
SystemResourceInformation();
}
// 判断进程链表是否为空
if(head.next == null){
return true;
}
// 初始化参数 将一维数组 ==> 二维数组
int index = 0; // 记录下标
int[][] allocation = new int[processLength()][numberOfResourcTypes];
int[][] need = new int[processLength()][numberOfResourcTypes];
String[] processName = new String[processLength()];
Process temp = head;
while(true){
if(temp.next == null){
break;
}
processName[index] = temp.next.getName();
allocation[index] = temp.next.getAllocationResource();
need[index] = temp.next.getNeedResource();
index++;
temp = temp.next;
}
// 结束标志
int end = processLength()-1;
int numIndex = 0; // 记录顺序下标
int[] num = new int[processLength()]; // 记住进程顺序
boolean[] flag = new boolean[processLength()]; // 标志位
int[] available = Available.clone();
// 初始化赋值
for (int i = 0; i < processLength(); i++) {
num[i] = -1;
flag[i] = false;
}
// 开始安全检测
while(end >= 0){
for (int i = 0; i < processLength(); i++) {
if(flag[i] == false){
boolean IsFlag = true; // 判断是否能分配资源
for (int j = 0; j < numberOfResourcTypes; j++) {
if(available[j] < need[i][j]){
IsFlag = false;
break;
}
}
if(IsFlag == true){
for (int j = 0; j < numberOfResourcTypes; j++) {
available[j] += allocation[i][j];
}
num[numIndex] = i+1;
numIndex++;
flag[i] = true;
}
}
}
end--;
}
for (int i = 0; i < processLength(); i++) {
if(flag[i] == false){
System.out.println("该进程不安全!!!");
return false;
}
}
System.out.println("进程安全!!");
System.out.print("进程顺序: ");
for (int i = 0; i < num.length; i++) {
if(i == num.length-1){
System.out.print(bottomNode(num[i]).getName());
}else
System.out.print(bottomNode(num[i]).getName()+" --> ");
}
System.out.println();
return true;
}
银行家算法
if(choice == 1){
// 银行家算法
boolean flag = false; // 判读是否请求失败
int[] request = new int[numberOfResourcTypes];
System.out.print("提出请求的资源进程名:");
String processName = new Scanner(System.in).next().trim();
System.out.print("请求资源数量:");
Scanner sc =new Scanner(System.in);
for (int i = 0; i < request.length; i++) {
request[i] = sc.nextInt();
if(request[i]>Available[i]){
System.out.println("请求资源失败!");
flag = true;
break;
}
}
if(flag == true) continue;
// 遍历进程链表
int[] allocation;
int[] need;
int[] max;
Process temp = head;
while(true) {
if(temp.next == null) {
System.out.println("没有该进程!!!");
break;
}
if(temp.next.getName().equals(processName)) {
max = temp.next.getMaxResource();
allocation = temp.next.getAllocationResource();
need = temp.next.getNeedResource();
for (int i = 0; i < numberOfResourcTypes; i++) {
if((allocation[i] + request[i])> max[i] || need[i] < request[i]){
System.out.println("请求资源失败!!");
flag = true;
break;
}
}
if(flag == true) break;
for (int i = 0; i < numberOfResourcTypes; i++) {
allocation[i] += request[i];
need[i] -= request[i];
Available[i] -= request[i];
}
// 安全序列检测
if(IsSafety()){
System.out.println("请求资源成功!!!");
break;
}else{
System.out.println("请求资源失败!!!恢复数据");
// 恢复原数据
for (int i = 0; i < numberOfResourcTypes; i++) {
allocation[i] -= request[i];
need[i] += request[i];
Available[i] += request[i];
}
break;
}
}
temp = temp.next;
}
随机分配算法
// 随机分配算法
boolean flag = false; // 判读是否请求失败
int[] request = new int[numberOfResourcTypes];
System.out.print("提出请求的资源进程名:");
String processName = new Scanner(System.in).next().trim();
System.out.print("请求资源数量:");
Scanner sc =new Scanner(System.in);
for (int i = 0; i < request.length; i++) {
request[i] = sc.nextInt();
if(request[i]>Available[i]){
System.out.println("请求资源失败!");
flag = true;
break;
}
}
if(flag == true) continue;
// 遍历进程链表
int[] allocation;
int[] need;
int[] max;
Process temp = head;
while(true) {
if (temp.next == null) {
System.out.println("没有该进程!!!");
break;
}
if (temp.next.getName().equals(processName)) {
max = temp.next.getMaxResource();
allocation = temp.next.getAllocationResource();
need = temp.next.getNeedResource();
for (int i = 0; i < numberOfResourcTypes; i++) {
if((allocation[i] + request[i])> max[i] || need[i] < request[i]){
System.out.println("请求资源失败!!");
flag = true;
break;
}
}
if(flag == true) break;
for (int i = 0; i < numberOfResourcTypes; i++) {
allocation[i] += request[i];
need[i] -= request[i];
Available[i] -= request[i];
}
break;
}
temp = temp.next;
}
}
实现效果
我直接用文件读入的形式演示
首先,检查当前进程资源是否安全
然后,提出请求
银行家算法和随机分配算法的区别
银行家算法:如果发现死锁会立即还原数据
随机分配算法:能给即给,不进行安全检测,发生死锁无法挽回!
好啦,讲到现在,其实大家更想百嫖,我能理解大家的心情,你和我们讲那么多,又不给我们实现的代码,这怎么操作啊?
不急,咱上源码(完整)
彩蛋
文件目录如下:输入文件就自己录入叭!
Applicaion.java
package com.Al_tair;
import com.Al_tair.display.CoreProcessor;
import java.io.IOException;
/**
* @author Al_tair
* @date 2021/12/20-10:50
* 启动类
*/
public class Application {
public static void main(String[] args) throws IOException {
new CoreProcessor();
}
}
Process.java
package com.Al_tair.entity;
import java.util.Arrays;
/**
* @author Al_tair
* @date 2021/12/22-16:15
*/
public class Process {
// 进程名(unique)
private String name;
// 最大资源
private int[] MaxResource;
// 分配资源
private int[] AllocationResource;
// 需要资源
private int[] NeedResource;
// 链表
public Process next; // 指向下一个节点
public String getName() {
return name;
}
public int[] getAllocationResource() {
return AllocationResource;
}
public int[] getMaxResource() {
return MaxResource;
}
public int[] getNeedResource() {
return NeedResource;
}
// 无参/有参构造函数
public Process(){}
public Process(String name,int[] MaxResource,int[] AllocationResource,int[] NeedResource){
this.name = name;
this.MaxResource = MaxResource;
this.AllocationResource = AllocationResource;
this.NeedResource = NeedResource;
}
@Override
public String toString() {
return "Process{" +
"name='" + name + '\'' +
", MaxResource=" + Arrays.toString(MaxResource) +
", AllocationResource=" + Arrays.toString(AllocationResource) +
", NeedResource=" + Arrays.toString(NeedResource) +
", next=" + next +
'}';
}
public String specificDisplay(int numberOfResourcTypes, int[] Available,int length,Process head){
String s = "";
s += numberOfResourcTypes + "\n";
for (int i = 0; i < numberOfResourcTypes; i++) {
s += Available[i]+ "\n";
}
Process temp = head.next;
int[] max = new int[numberOfResourcTypes];
int[] allocation = new int[numberOfResourcTypes];
int[] need = new int[numberOfResourcTypes];
for (int i = 0; i < length; i++) {
max = temp.MaxResource;
allocation = temp.AllocationResource;
need = temp.NeedResource;
for (int j = 0; j < numberOfResourcTypes*3+1; j++) {
if(j==0) {
s += temp.getName() + "\n";
}else if(j<=3 && j>=1) {
s += max[j - 1] + "\n";
}else if(j<=6 && j>=4) {
s += allocation[j - 4] + "\n";
}
else if(j<=9 && j>=7) {
s += need[j - 7] + "\n";
}
}
temp = temp.next;
}
return s;
}
}
CoreProcess.java
package com.Al_tair.display;
import com.Al_tair.entity.Process;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
/**
* @author Al_tair
* @date 2021/12/22-15:44
* @version 1.0
*/
public class CoreProcessor {
// 资源种类数 例如:A B C
private int numberOfResourcTypes = 0;
// 创建链表头 用来连接所有进程以及资源数
private Process head = new Process();
// 系统可分配资源数
int[] Available;
/**
* *******************************
* 共享资源分配与银行家算法
* 1.系统资源分配信息
* 2.添加进程及进程信息
* 3.删除进程及进程信息
* 4.查找进程及进程信息
* 5.检查是否序列安全
* 6.提出请求资源
* 7.读入文件数据
* 8.保存文件数据
* 9.清除进程和资源信息
* 10.退出系统
* *******************************
* 输入序号(1~10):
*/
public CoreProcessor() throws IOException {
while(true){
System.out.println("*******************************");
System.out.println(" 共享资源分配与银行家算法 ");
System.out.println(" 1.系统资源分配信息 ");
System.out.println(" 2.添加进程及进程信息 ");
System.out.println(" 3.删除进程及进程信息 ");
System.out.println(" 4.查找进程及进程信息 ");
System.out.println(" 5.检查是否序列安全 ");
System.out.println(" 6.提出请求资源 ");
System.out.println(" 7.读入文件数据 ");
System.out.println(" 8.保存文件数据 ");
System.out.println(" 9.清除进程和资源信息 ");
System.out.println(" 10.退出系统 ");
System.out.println("*******************************");
System.out.print("输入序号(1~10):");
// 序号必须在1~10之间
int choice = new Scanner(System.in).nextInt();
if(!(choice <=10 && choice>=1)){
continue;
}
switch (choice){
case 1: SystemResourceInformation();
break;
case 2: AddProcessesAndProcessInformation();
break;
case 3: DeleteProcessesAndProcessInformation();
break;
case 4: SearchForProcessesAndProcessInformation(head);
break;
case 5: IsSafety();
break;
case 6: AskForRequest();
break;
case 7: ReadFile();
break;
case 8: SaveFile();
break;
case 9: ClearProcessAndResourceInformation();
break;
case 10: ExitSystem();
break;
default:
System.out.println("impossible");
}
}
}
//1.系统资源分配信息
private void SystemResourceInformation(){
if(numberOfResourcTypes != 0) return;
System.out.println("*******************************");
System.out.println(" 系统资源分配信息 ");
System.out.print(" 输入系统资源种类数:");
numberOfResourcTypes = new Scanner(System.in).nextInt();
if(numberOfResourcTypes<0){
System.out.println("输入系统资源种类数错误!返回核心处理器");
numberOfResourcTypes=0;
return;
}
Available = new int[numberOfResourcTypes];
System.out.print(" 输入"+numberOfResourcTypes+"个系统可分配资源数(available):");
Scanner sc = new Scanner(System.in);
for (int i = 0; i < numberOfResourcTypes; i++) {
Available[i] = sc.nextInt();
}
System.out.println(" 输入完成!!! ");
System.out.println("*******************************");
}
// 2.添加进程及进程信息
private void AddProcessesAndProcessInformation(){
if(numberOfResourcTypes == 0){
System.out.println("系统资源分配信息未输入!!!");
SystemResourceInformation();
}
while (true){
System.out.println("*******************************");
System.out.println(" 添加进程及进程信息 ");
System.out.println(" 1.添加进程 ");
System.out.println(" 2.退出 ");
System.out.print("输入序号(1~2):");
// 序号必须在1~2之间
int choice = new Scanner(System.in).nextInt();
if(choice == 2){
System.out.println("添加进程完成!");
System.out.println("*******************************");
return;
}
if(!(choice <=2 && choice>=1)){
System.out.println("*******************************");
continue;
}
// 开始添加进程信息
// processName
System.out.print("\n输入进程名:");
String processName = new Scanner(System.in).next().trim();
// Max
System.out.print("输入"+numberOfResourcTypes+"个最大需求资源数(max):");
int[] max = new int[numberOfResourcTypes];
Scanner sc = new Scanner(System.in);
for (int i = 0; i < max.length; i++) {
max[i] = sc.nextInt();
}
// Allocation Need
System.out.print("输入"+numberOfResourcTypes+"个已分配资源数(allocation):");
int[] allocation = new int[numberOfResourcTypes];
int[] need = new int[numberOfResourcTypes];
for (int i = 0; i < numberOfResourcTypes; i++) {
allocation[i] = sc.nextInt();
need[i] = max[i] - allocation[i];
}
// 检验是否出错 及其进程名有无重复
if(IsSameName(processName)){
System.out.println("进程名重复了,请重新输入");
continue;
}
for (int i = 0; i < numberOfResourcTypes; i++) {
if(max[i]<0 || allocation[i]<0 || need[i]<0){
System.out.println("进程数据有误,返回核心处理器!!!");
return;
}
}
// 添加新进程到新链表
Process temp = head;
// 遍历链表,找到最后
while(true){
if(temp.next == null){
break;
}
temp = temp.next;
}
// 当退出while循环时候,temp就指向最后一个节点
temp.next = new Process(processName,max,allocation,need);
// 提示进程是否安全
// IsSafety();
System.out.println();
System.out.println("*******************************");
}
}
// 3.删除进程及进程信息
private void DeleteProcessesAndProcessInformation(){
if(numberOfResourcTypes == 0){
System.out.println("系统资源分配信息未输入!!!");
SystemResourceInformation();
}
// 判断进程链表是否为空
if(head.next == null){
System.out.println("没有该进程链表");
return;
}
while(true) {
System.out.println("*******************************");
System.out.println(" 删除进程及进程信息 ");
System.out.println(" 1.删除进程 ");
System.out.println(" 2.退出 ");
System.out.print("输入序号(1~2):");
// 序号必须在1~2之间
int choice = new Scanner(System.in).nextInt();
if (choice == 2) {
System.out.println("删除进程完成!");
System.out.println("*******************************");
return;
}
if (!(choice <= 2 && choice >= 1)) {
System.out.println("*******************************");
continue;
}
// 开始删除进程信息
// processName
System.out.print("\n输入需要删除的进程名:");
String processName = new Scanner(System.in).next().trim();
// 遍历进程链表
Process temp = head;
while(true) {
if (temp.next == null) {
System.out.println("没有该进程");
break;
}
if (temp.next.getName().equals(processName)) {
temp.next = temp.next.next;
break;
}
temp = temp.next;
}
System.out.println("*******************************");
}
}
// 4.查找进程及进程信息
private void SearchForProcessesAndProcessInformation(Process top){
if(numberOfResourcTypes == 0){
System.out.println("系统资源分配信息未输入!!!");
SystemResourceInformation();
}
// 判断进程链表是否为空
if(head.next == null){
System.out.println("无进程数据!");
return;
}
// 因为头节点不能动,因此需要一个辅助变量
Process temp = top;
while (true){
if(temp.next == null){
break;
}
temp = temp.next;
System.out.println("进程名: "+temp.getName()+
" max: "+ Arrays.toString(temp.getMaxResource())+
" allocation: " +Arrays.toString(temp.getAllocationResource())+
" need: " +Arrays.toString(temp.getNeedResource()));
}
}
// 5.检查是否序列安全
private boolean IsSafety(){
if(numberOfResourcTypes == 0){
System.out.println("系统资源分配信息未输入!!!");
SystemResourceInformation();
}
// 判断进程链表是否为空
if(head.next == null){
return true;
}
// 初始化参数 将一维数组 ==> 二维数组
int index = 0; // 记录下标
int[][] allocation = new int[processLength()][numberOfResourcTypes];
int[][] need = new int[processLength()][numberOfResourcTypes];
String[] processName = new String[processLength()];
Process temp = head;
while(true){
if(temp.next == null){
break;
}
processName[index] = temp.next.getName();
allocation[index] = temp.next.getAllocationResource();
need[index] = temp.next.getNeedResource();
index++;
temp = temp.next;
}
// 结束标志
int end = processLength()-1;
int numIndex = 0; // 记录顺序下标
int[] num = new int[processLength()]; // 记住进程顺序
boolean[] flag = new boolean[processLength()]; // 标志位
int[] available = Available.clone();
// 初始化赋值
for (int i = 0; i < processLength(); i++) {
num[i] = -1;
flag[i] = false;
}
// 开始安全检测
while(end >= 0){
for (int i = 0; i < processLength(); i++) {
if(flag[i] == false){
boolean IsFlag = true; // 判断是否能分配资源
for (int j = 0; j < numberOfResourcTypes; j++) {
if(available[j] < need[i][j]){
IsFlag = false;
break;
}
}
if(IsFlag == true){
for (int j = 0; j < numberOfResourcTypes; j++) {
available[j] += allocation[i][j];
}
num[numIndex] = i+1;
numIndex++;
flag[i] = true;
}
}
}
end--;
}
for (int i = 0; i < processLength(); i++) {
if(flag[i] == false){
System.out.println("该进程不安全!!!");
return false;
}
}
System.out.println("进程安全!!");
System.out.print("进程顺序: ");
for (int i = 0; i < num.length; i++) {
if(i == num.length-1){
System.out.print(bottomNode(num[i]).getName());
}else
System.out.print(bottomNode(num[i]).getName()+" --> ");
}
System.out.println();
return true;
}
// 6.提出请求资源
private void AskForRequest(){
if(numberOfResourcTypes == 0){
System.out.println("系统资源分配信息未输入!!!");
SystemResourceInformation();
}
if(head.next == null){
System.out.println("无进程链表!!!");
return;
}
while(true){
System.out.println("*******************************");
System.out.println(" 提出请求资源 ");
System.out.println(" 1.银行家算法 ");
System.out.println(" 2.随机分配算法 ");
System.out.println(" 3.退出 ");
// 序号必须在1~3之间
int choice = new Scanner(System.in).nextInt();
if(choice == 3){
System.out.println("添加进程完成!");
System.out.println("*******************************");
return;
}
if(!(choice <=3 && choice>=1)){
System.out.println("*******************************");
continue;
}
if(choice == 1){
// 银行家算法
boolean flag = false; // 判读是否请求失败
int[] request = new int[numberOfResourcTypes];
System.out.print("提出请求的资源进程名:");
String processName = new Scanner(System.in).next().trim();
System.out.print("请求资源数量:");
Scanner sc =new Scanner(System.in);
for (int i = 0; i < request.length; i++) {
request[i] = sc.nextInt();
if(request[i]>Available[i]){
System.out.println("请求资源失败!");
flag = true;
break;
}
}
if(flag == true) continue;
// 遍历进程链表
int[] allocation;
int[] need;
int[] max;
Process temp = head;
while(true) {
if(temp.next == null) {
System.out.println("没有该进程!!!");
break;
}
if(temp.next.getName().equals(processName)) {
max = temp.next.getMaxResource();
allocation = temp.next.getAllocationResource();
need = temp.next.getNeedResource();
for (int i = 0; i < numberOfResourcTypes; i++) {
if((allocation[i] + request[i])> max[i] || need[i] < request[i]){
System.out.println("请求资源失败!!");
flag = true;
break;
}
}
if(flag == true) break;
for (int i = 0; i < numberOfResourcTypes; i++) {
allocation[i] += request[i];
need[i] -= request[i];
Available[i] -= request[i];
}
// 安全序列检测
if(IsSafety()){
System.out.println("请求资源成功!!!");
break;
}else{
System.out.println("请求资源失败!!!恢复数据");
// 恢复原数据
for (int i = 0; i < numberOfResourcTypes; i++) {
allocation[i] -= request[i];
need[i] += request[i];
Available[i] += request[i];
}
break;
}
}
temp = temp.next;
}
}else{
// 随机分配算法
boolean flag = false; // 判读是否请求失败
int[] request = new int[numberOfResourcTypes];
System.out.print("提出请求的资源进程名:");
String processName = new Scanner(System.in).next().trim();
System.out.print("请求资源数量:");
Scanner sc =new Scanner(System.in);
for (int i = 0; i < request.length; i++) {
request[i] = sc.nextInt();
if(request[i]>Available[i]){
System.out.println("请求资源失败!");
flag = true;
break;
}
}
if(flag == true) continue;
// 遍历进程链表
int[] allocation;
int[] need;
int[] max;
Process temp = head;
while(true) {
if (temp.next == null) {
System.out.println("没有该进程!!!");
break;
}
if (temp.next.getName().equals(processName)) {
max = temp.next.getMaxResource();
allocation = temp.next.getAllocationResource();
need = temp.next.getNeedResource();
for (int i = 0; i < numberOfResourcTypes; i++) {
if((allocation[i] + request[i])> max[i] || need[i] < request[i]){
System.out.println("请求资源失败!!");
flag = true;
break;
}
}
if(flag == true) break;
for (int i = 0; i < numberOfResourcTypes; i++) {
allocation[i] += request[i];
need[i] -= request[i];
Available[i] -= request[i];
}
break;
}
temp = temp.next;
}
}
}
}
// 7.读入文件数据
public void ReadFile() {
if(numberOfResourcTypes != 0){
System.out.println("系统资源分配信息已经输入!!!");
return;
}
List input = new ArrayList();
System.out.println("请问你要读入文件的文件名:");
String s = new Scanner(System.in).next();
String pathname = "E:\\enableCleanProject\\SharedResourceAllocationAndBankerAlgorithm\\OSAlgorithm\\src\\" + s;
try (FileReader reader = new FileReader(pathname);BufferedReader br = new BufferedReader(reader)) {
String line;
while ((line = br.readLine()) != null) {
// 一次读入一行数据
String[] str =line.split(" ");
input.add(str[0]);
}
} catch (IOException e) {
e.printStackTrace();
}
numberOfResourcTypes = Integer.valueOf(input.get(0).toString());
String processName = "";
Available = new int[numberOfResourcTypes];
for (int i = 1; i <= numberOfResourcTypes; i++) {
Available[i-1] = Integer.valueOf(input.get(i).toString());
}
int count = (input.size()-(1+numberOfResourcTypes))/(numberOfResourcTypes*3+1);
int[][] max = new int[count][numberOfResourcTypes];
int[][] allocation = new int[count][numberOfResourcTypes];
int[][] need = new int[count][numberOfResourcTypes];
// 添加新进程到新链表
Process temp = head;
while(count > 0){
processName = input.get((1+numberOfResourcTypes)+(5-count)*(numberOfResourcTypes*3+1)).toString();
int num =(1+numberOfResourcTypes)+(5-count)*(numberOfResourcTypes*3+1);
int index = 0;
for (int i = num+1; i <= num+numberOfResourcTypes; i++) {
max[5-count][index] = Integer.valueOf(input.get(i).toString());
index++;
}
index = 0;
for (int i = num+1+numberOfResourcTypes; i <= num+numberOfResourcTypes*2; i++) {
allocation[5-count][index] = Integer.valueOf(input.get(i).toString());
index++;
}
index = 0;
for (int i = num+1+numberOfResourcTypes*2; i <= num+numberOfResourcTypes*3; i++) {
need[5-count][index] = Integer.valueOf(input.get(i).toString());
index++;
}
temp.next = new Process(processName,max[5-count],allocation[5-count],need[5-count]);
temp = temp.next;
count--;
}
System.out.println("读入成功");
}
// 8.保存文件数据
public void SaveFile() throws IOException {
//将写入转化为流的形式
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\enableCleanProject\\SharedResourceAllocationAndBankerAlgorithm\\OSAlgorithm\\src\\dataOutput.txt"));
Process temp = head.next;
//一次写一行
String output = head.specificDisplay(numberOfResourcTypes,Available,processLength(),head);
bw.write(output);
bw.newLine(); //换行用
//关闭流
bw.close();
System.out.println("写入成功");
}
// 9.清除进程和资源信息
private void ClearProcessAndResourceInformation(){
numberOfResourcTypes = 0;
head.next = null;
}
// 10.退出系统
private void ExitSystem(){
System.out.println("期待你的回来!共享资源分配与银行家算法等你!");
System.exit(0);
}
/**
* 附加功能 MyUtils
*/
// 进程长度
private int processLength(){
// 判断进程链表是否为空
if(head.next == null || numberOfResourcTypes == 0){
System.out.println("无进程数据!");
return 0;
}
// 因为头节点不能动,因此需要一个辅助变量
Process temp = head;
// 记录进程数量
int length = 0;
while (true){
if(temp.next == null){
break;
}
length++;
temp = temp.next;
}
return length;
}
// 判判进程名有没有重复
private boolean IsSameName(String processName){
// 判断进程链表是否为空
if(numberOfResourcTypes == 0){
System.out.println("无进程数据!");
return true;
}
// 因为头节点不能动,因此需要一个辅助变量
Process temp = head;
while (true){
if(temp.next == null){
break;
}
if(temp.next.getName().equals(processName)){
return true;
}
temp = temp.next;
}
return false;
}
// 查找链表中第n个节点
public Process bottomNode (int num){
// 判断进程链表是否为空
if(head.next == null || numberOfResourcTypes == 0){
System.out.println("无进程数据!");
return new Process();
}
Process temp = head.next;
while(--num > 0){
if(temp.next == null){
System.out.println("链表中无法找到该结点");
return new Process();
}
temp = temp.next;
}
return temp;
}
}