操作系统银行家算法Java实现彩虹姐专用版-程序员宅基地

技术标签: 算法  java  开发语言  

前言

        操作系统实验课需要才写的,在网上借鉴了各位圣贤的代码但是跟老师要求的不一样,所以在搞懂了算法的原理的前提下改动了代码,思想跟网上的都一样,结果输出的呈现不一样,适合写作业的时候直接拿来用。

银行家算法简介

银行家算法是操作系统的经典算法之一,用于避免死锁情况的出现。

一个新进程进入系统时,必须声明需要每种资源的最大数目,其数目不能超过系统所拥有的的资源总量。当进程请求一组资源时,系统必须首先确定是否有足够的资源分配给该进程,若有,再进一步计算在将这些资源分配给进程后,是否会使系统处于不安全状态如果不会才将资源分配给它,否则让进程等待。

算法中的主要的数据结构

  • Available一维数组:系统中可利用的资源数目
  • Max矩阵:每个进程对每种资源的最大需求
  • Allocation矩阵:每个进程已分配的各类资源的数目
  • Need矩阵:每个进程还需要的各类资源数
  • Work一维数组:当前进程可用的资源数

关系:Need[i,j] = Max[i,j] - allocation[i, j]

求安全序列算法:在定义5个进程3个资源并且进程分配到了部分资源数(代码部分都已经做好了初始化操作直接显示)重复循环5次(既进程数),每次遍历每个进程将work与其need对比,每次的循环会取出一个可以调度的进程并加入到安全序列中,接着将进程号的finsh设置为true下一次遍历将不再调度,若5次循环中有一次没有取到可以调度的进程则安全序列数组的大小小于进程数目,得到结果为不安全,反之亦然。

资源请求:输入要得到资源的进程号,输入3个资源数目,将资源分配好了后再进行一次安全序列检查,判断能否分配资源,实际上分配的资源不满足进程的need则为不安全。

代码如下:


import java.util.Scanner;

public class Bank {
	//声明并初始化部分变量
 static int[] available= {10,5,7}; // available表示还有多少可用资源
 static int[][] max= {
   {7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,0,3}};// Max表示各进程对资源的最大需求数
 static int[][] allocation= {
   {0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2}};// 表示已分配的资源矩阵
 static int[][] need;// need矩阵表示各进程最多还需要多少资源
 static int[] request; // request表示进程此次申请的各种资源数
 static int[] sequence_safe; // 安全序列数组
 static int process_nums; // 定义进程的数量
 static int resource_nums; // 定义资源的种类数量
 static boolean flag; // 定义标志变量
 static int[] work;//进程可用的资源数
 static int[][] works;//用于打印每个进程的work信息
 static boolean[] finish;

 //资源初始化
  static void init() {
     // 输入进程数
     Scanner in = new Scanner(System.in);
     /*
      * 先不用调用in.close()方法关闭,在main函数中我们还需要 输入,如果这时候关闭了在运行时会报错(不能找到元素) Exception in
      * thread "main" java.util.NoSuchElementException
      */
     process_nums = 5;
     resource_nums = 3;
     // 初始化数组
     request = new int[resource_nums]; // request的长度等于资源种类,某个进程分别申请的各个资源个数
     sequence_safe = new int[process_nums];//安全序列数组长度等于进程数
     need = new int[process_nums][resource_nums];
     //计算余下资源数
     for(int j=0;j<process_nums;j++) {
    	 for(int i=0;i<resource_nums;i++) {
    		 available[i]=available[i]-allocation[j][i];
    	 }
     }
     // 计算需求矩阵
     for (int i = 0; i < process_nums; i++) {
         for (int j = 0; j < resource_nums; j++) {
             need[i][j] = max[i][j] - allocation[i][j];//需求每个进程的需求等于最大-已分配
         }
     }
 }
  //查看当状态表
 static void show(int select) {
	 if(select==1) {
		 System.out.println("状态表:");
		 System.out.println("Process\t\t|Max\t\t|Allocation\t|Need\t\t|Available\t|");
		 for(int i = 0;i<process_nums;i++){
	         System.out.print(i+"                ");
	         for(int m = 0;m<resource_nums;m++)System.out.print(max[i][m]+"  ");//max
	         System.out.print("        ");
	         for(int m = 0;m<resource_nums;m++) System.out.print(allocation[i][m]+"  ");//allocation
	         System.out.print("        ");
	         for(int m = 0;m<resource_nums;m++) System.out.print(need[i][m]+"  "  );//need
	         System.out.print("        ");
	         for(int m = 0;m<resource_nums;m++) {
	        	 if (i==0) {
					System.out.print(available[m]+"   ");
				}
	         }
	         System.out.println();
	     } 
	 }else {
		 System.out.println("安全序列表:");
		 System.out.println("Process\t\t|Work\t\t|Need\t\t|Allocation\t|Work+Allocation\t|Finish");
		 for(int temp:sequence_safe) {
			 System.out.print(temp+"                ");
			 for(int m = 0;m<resource_nums;m++)System.out.print(works[temp][m]+"  ");//max
	         System.out.print("        ");
	         for(int m = 0;m<resource_nums;m++) System.out.print(need[temp][m]+"  "  );//need
	         System.out.print("        ");
	         for(int m = 0;m<resource_nums;m++) System.out.print(allocation[temp][m]+"  ");//allocation
	         System.out.print("        ");
	         for(int m = 0;m<resource_nums;m++)System.out.print(allocation[temp][m]+works[temp][m]+"  ");//max
	         System.out.print("             "+finish[temp]+"  ");
	         System.out.print("        ");
	         System.out.println();
		 }
	}	 
 }
 //将work与need比较
 // 当m中的全部元素分别大于或等于n中的全部元素的时候返回true,否则返回false
 static boolean compare(int[] m, int[] n) {
     for (int i = 0; i < resource_nums; i++) {
         if (m[i] < n[i])
             return false;
     }
     return true;
 }
 //求安全序列
 static boolean safe() {
	 works=new int[process_nums][resource_nums];
     work = new int[resource_nums];
     finish = new boolean[process_nums];
     sequence_safe = new int[process_nums];
     int num = 0; // 已分配进程的个数
     int l = 0;
     // 定义一个work数组来存储available,因为work中途会发生变化,不确定是否为最终结果
     for (int i = 0; i < resource_nums; i++) {
         work[i] = available[i];
         works[0][i]=available[i];
     }
     for (int i = 0; i < process_nums; i++) {
         finish[i] = false;
     }
     /* 核心算法有多少个进程就循环多少次,每次循环遍历need一次,若满足条件,释放资源后num+1 */
     for (int i = 0; i < process_nums; i++) {
         if (num == process_nums) break;// 若进程已全部加入分配完成
         for (int j = 0; j < process_nums; j++) {
             if (finish[j]) {//若该进程已经完成则跳过这个进程
            	 continue;
             }else {
                 if (compare(work, need[j])) {//将work即可用的资源与该进程的need比较,work大于即可进入分配
                     finish[j] = true; // 将进程j标记为已分配
                     // 将进程j加入安全序列
                     sequence_safe[l++] = j; 
                     num++;
                     // 释放进程资源
                     for(int e=0;e<3;e++) {
                    	 works[j][e]=work[e];//把当前的word记录到words
                     }
                     for (int k = 0; k < resource_nums; k++) {
                         work[k] = work[k] + allocation[j][k];
                     }
                 }
             }
         }
     }
     //查看是否有进程为false有则不安全
     for (int i = 0; i < process_nums; i++) {
         if (!finish[i])
             return false;
     } 
     show(2);    
     // 输出安全序列
     System.out.print("安全序列为:");
     for (int i = 0; i < process_nums; i++) {
         System.out.print(sequence_safe[i] + " ");
     }
     System.out.println();
     return true;
 }
 //资源请求
 // 申请资源之后的检测
 static void resafe(int n) {// n为请求资源的进程编号3+
     if (compare(available, request) && compare(request,need[n])) {
         for (int i = 0; i < resource_nums; i++) { // 试分配资源
             allocation[n][i] = allocation[n][i] + request[i];
             need[n][i]=need[n][i]-request[i];
             available[i] = available[i] - request[i];
         }
         // 判断是否处于安全状态
         if (safe()) {
             System.out.println("允许进程" + n + "申请资源!");
         } else {
             System.out.println("处于非安全状态,不允许进程" + n + "申请资源!");
             for (int i = 0; i < resource_nums; i++) { // 把试分配资源回收
                 allocation[n][i] = allocation[n][i] - request[i];
                 need[n][i] = need[n][i] + request[i];
                 available[i] = available[i] + request[i];
             }
         }
     } else {
    	 System.out.println("申请资源越界!");
    	 return;
     }  
 }
 public static void main(String[] args) {
     Scanner in = new Scanner(System.in);
     int n; // 进程编号
     init();
     show(1);
     if (safe()) {
         System.out.println("存在安全序列,初始状态安全!");
     } else
         System.out.println("不存在安全序列,初始状态不安全!");

     System.out.print("请输入请求资源的进程号:");
     n=in.nextInt();
     System.out.println("请输入三类资源的数量");
     for(int i=0;i<resource_nums;i++) {
    	 request[i]=in.nextInt();
     }
     resafe(n);
 	}
}


 核心代码是参考了其他博主并一部分并改写了一部分,有错误还望指正

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_60499221/article/details/127430983

智能推荐

苹果快捷键怎么调出来_原来还有这么好用的CAD快捷键,文末附赠快捷键鼠标垫!留言走起...-程序员宅基地

文章浏览阅读141次。▼相信大家都看过一些大神做CAD,那个图纸真是做的又快又好看!当然大神们其实也就基础好一点,把快捷键记得过目不忘,所以接下来小编就教大家一个非常Skr的方法,保证你对这些快捷键过目不忘,文末更有免费鼠标垫领取,千万别错过哦!这个方法就是建立我们的思维导图了,文字看了可能会忘记,但是通过导图的方式,就会变成思维图形,更加符合我们大脑的思考习惯,就可以牢牢记住这些快捷键啦:▼例如我们看到下面的就是绘图..._苹果cad快捷键

MATLAB的GUI 程序设计_制作一个曲面光照效果的演示界面,如图所示,三个弹出式菜单分别用于选择曲面形式、-程序员宅基地

文章浏览阅读7.2k次,点赞7次,收藏60次。第七章 MATLAB的GUI 程序设计Chapter 8: Design of MATLAB of GUI programGUI(Graphical User Interfaces):由各种图形对象组成的用户界面,在这种用户界面下,用户的命令和对程序的控制是通过“选择”各种图形对象来实现的。目前90%以上的应用程序和软件都是在GUI下运行的。MATLAB有两种GUI用户界面控件的创建方式,基于命令行的方式用程序来制作和基于GUI的方式制作。这里主要介绍基于GUI的方式。MATLAB 的._制作一个曲面光照效果的演示界面,如图所示,三个弹出式菜单分别用于选择曲面形式、

MT7628开发环境搭建_undefined reference to `llseek-程序员宅基地

文章浏览阅读2.1k次。参考openwrt 快速入门1.环境搭建1.1Ubuntu dockerhttps://www.runoob.com/docker/ubuntu-docker-install.html​1.1.1使用官方安装脚本自动安装安装命令如下:curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun​ps: 我已经放弃用deepin编译旧版openwrt ,修复了十几个bug还是有bug,无敌下载14.04版本docke_undefined reference to `llseek

13 Kubectl命令概览_kube_ps1关闭-程序员宅基地

文章浏览阅读81次。kubectx:用于切换kubernetes context kube-ps1:为命令行终端增加$PROMPT字段 kube-shell:交互式带命令提示的kubectl终端kube-shell开源项目kube-shell可以为kubectl提供自动的命令提示和补全,使用起来特别方便,推荐给大家。Kube-shell有以下特性:命令提示,给出命令的使用说明 自动补全,列出可选命令并可以通过tab键自动补全,支持模糊搜索 高亮 使用tab键可以列出可选的对象 vim模式M..._kube_ps1关闭

ensp各种报错积累(以及解决方法)_ensp配置路由地址时错误-程序员宅基地

文章浏览阅读1k次,点赞11次,收藏9次。此报错的意思是请续订默认配置,就是让你去一级一级的删除,首先删除你设置的允许vlan通过的命令,然后去取消掉更改的端口类型命令(就是在配置命令前面加一个undo),再去更改端口类型就成功了。此报错的意思是已经加入了接口,不能在修改模式,所以需要先去把端口全部删除,在修改模式即可成功。他的意思就是说这个IP地址已经配置了,不需要在配置了。2.修改链路聚合模式的时候。3.更改IP地址的时候。_ensp配置路由地址时错误

经典JS-序列号_ucfp:74a28a8b-b3fb-4602-ca5f-0ebdf880c1ff-16927960-程序员宅基地

文章浏览阅读10w+次。3D0E1D4E75686FA0FF1C6F6F626F6F6F6F6F6F6F8F381B2FFF2D6FEF396F6F6A1B6E6F6D762B39E3021B282C725C726F4F6F6F6F5F5F5C330E1F06251C335B5E0D580E5E095D575B0E56560B5F0B41051C6F9F4FCC60636EBE7FBE7A3E637EB613394327_ucfp:74a28a8b-b3fb-4602-ca5f-0ebdf880c1ff-1692796091560

随便推点

Accessing static Data and Functions in Legacy C_setyearanddayofyear-程序员宅基地

文章浏览阅读1.1k次。http://www.renaissancesoftware.net/blog/archives/430http://www.renaissancesoftware.net/blog/archives/450It’s a new year; last year was a leap year; so the quadrennial reports of leap y_setyearanddayofyear

vue把字符串分割成等长的若干字符串,根据特定字符分割字符串_vue 分割字符串-程序员宅基地

文章浏览阅读1.6w次,点赞2次,收藏20次。把字符串分割成等长的若干字符串,根据特定字符分割字符串_vue 分割字符串

朴素贝叶斯分类器的例子_朴素贝叶斯分类器 例子-程序员宅基地

文章浏览阅读1.1k次。一、病人分类的例子让我从一个例子开始讲起,你会看到贝叶斯分类器很好懂,一点都不难。某个医院早上收了六个门诊病人,如下表。  症状  职业   疾病  打喷嚏 护士   感冒   打喷嚏 农夫   过敏   头痛  建筑工人 脑震荡   头痛  建筑工人 感冒   打喷嚏 教师   感冒   头痛  教师   脑震荡现在又来了第七个病人,是一个打喷嚏的建筑工人。请问他患上感冒的概率有多大?根据贝叶斯..._朴素贝叶斯分类器 例子

当mysql数据库转换为sqlserver数据库时常见报错_mysql 数据导出在sqlserver不能用-程序员宅基地

文章浏览阅读527次。↵下面是我在把mysql数据库转换为sqlserver数据库时候遇到过的一些错,踩过的坑,把它总结下来防止以后再出错。报错 1:com.microsoft.sqlserver.jdbc.SQLServerException: 仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'user_student'中的标识列指定显式值。出错原因:当mysql数据库转换为sqlserver数据库时,如果第一个id设置为自动递增,那么String sql = "..._mysql 数据导出在sqlserver不能用

LeetCode 刷题常用数据结构(Java 中的实现)_javalist集合map组合刷题 leetcode-程序员宅基地

文章浏览阅读1.9k次,点赞4次,收藏27次。记录常用数据结构(栈、队列、数组、列表、字符串、集合等),在 Java 中如何使用它的实现类。_javalist集合map组合刷题 leetcode

Visual Studio Code 设置成中文_visualstudiocode中文-程序员宅基地

文章浏览阅读6.7k次,点赞5次,收藏4次。Visual Studio Code 编辑器设置成中文 分2个步骤1、【查看】--【扩展】(Ctrl+Shift+X) 在扩展:商店中输入Chinese,搜索到 适用于 VS Code 的中文(简体)语言包,点击安装; 2、Ctrl+Shift+P,调出搜索框,输入 Configure Display Language,选中此配置项; 把配置页面中的"..._visualstudiocode中文