使用java實現(xiàn)銀行家算法
銀行家算法核心
先尋找滿足系統(tǒng)當前剩余的資源量(avaliable )>=進程運行所需的資源數(shù)的進程(need),再假設這個進程安全校驗是成功的,當這個進程運行完畢后,釋放資源后,現(xiàn)在系統(tǒng)當前剩余的資源(avaliable)=avaliable+該線程之前已分配的資源(allocation) ,將該節(jié)點進程設為處理時忽略進程,再以上條件為前提進行安全校驗。
安全校驗:一個進程獲得資源后,運行完畢,釋放之前分配的資源,其他的線程可以繼續(xù)運行,而不會造成死鎖。
這樣就會產(chǎn)生回溯。
滿足條件:是否存在一個進程運行所需的資源數(shù)<=當前系統(tǒng)剩余的資源數(shù)。
查找操作:先判斷回溯的步長(層數(shù))是否等于節(jié)點的個數(shù),如果等于說明已經(jīng)找到了正確路徑,返回真給上一層,如果不滿足,則看一下此層是否存在滿足條件的節(jié)點,如果存在,這一該節(jié)點為回溯點開始查找操作。如果都不存在,說明上一層的回溯點不是我們要找的節(jié)點,返回假給上一層,并回溯回到上一層節(jié)點,將忽略標記清楚,換另一個滿足條件的節(jié)點繼續(xù)在進行查找操作。
先以一個滿足條件的節(jié)點進行忽略標記(下一次查找時可忽略此節(jié)點),回溯的步長加一,再進行查找操作(下一層)。
import java.util.Arrays;
public class BanksTest {
// 用于存儲預操作后的資源變化
static int[] new_Avaliable = null;
// 用于存儲預操作的完成度
static boolean[] new_finish = null;
// 用于保存最終的進程執(zhí)行順序,初始化為非法進程-1
static int right[] = { -1, -1, -1, -1, -1 };
public static void main(String[] args) {
// 最大需求量
int[][] max = { { 7, 5, 3 }, { 3, 2, 2 }, { 9, 0, 2 }, { 2, 2, 2 }, { 4, 3, 3 } };
// 當前系統(tǒng)可用資源量
int[] avaliable = { 3, 3, 2 };
// 每個進程運行還需資源量
int[][] need = new int[5][3];
// 每個進程已分配的資源量
int[][] allocation = { { 0, 1, 0 }, { 2, 0, 0 }, { 3, 0, 2 }, { 2, 1, 1 }, { 0, 0, 2 } };
// 用于第一深度預判的初始化
boolean finish[] = { false, false, false, false, false };
// 獲取每個進程運行時還需的資源量
for (int i = 0; i < max.length; i++) {
for (int j = 0; j < max[i].length; j++) {
need[i][j] = max[i][j] - allocation [i][j];
}
}
// 創(chuàng)建遞歸深度
int deep = 0;
// 調(diào)用回溯遞歸算法
deepCheck(avaliable, allocation, need, finish, deep, right);
int i = 0;
// 查看最終的安全序列的值,看是否存在初始的非法進程,如果存在,則說明該案例不存在安全的進程執(zhí)行順序
for (; i < right.length; i++) {
if (right[i] == -1) {
break;
}
}
if (i < right.length) {
System.out.println("該案例不存在安全的進程執(zhí)行順序");
return;
}
// 打印安全的執(zhí)行順序
for (int j = 0; j < right.length; j++) {
System.out.println(right[j]);
}
}
// 完全遞歸回溯查找安全順序
public static boolean deepCheck(int[] avaliable, int[][] allocation, int[][] need, boolean finish[], int deep,
int right[]) {
int j = 0;
boolean flog = false;
// 如果深度為進程的個數(shù)數(shù)說明已經(jīng)查找到頭了,說明上一深度的進程是安全節(jié)點。因為上一深度的進程滿足了當前資源數(shù)大于或等于該進程運行所需的資源數(shù),且為安全序列中最后一個節(jié)點。
if (deep == need.length) {
return true;
}
// 遍歷所有節(jié)點進程開始查找,直到找到安全校驗成功的的節(jié)點進程
for (int i = 0; i < need.length; i++) {
// 對于未被標記的進行校驗,已被標記的為已被列為安全節(jié)點所以無需再進行校驗
if (!finish[i]) {
// 判斷當前的節(jié)點進程的剩余的資源量,是否滿足運行所需的資源量
for (j = 0; j < avaliable.length; j++) {
// 不滿足
if (need[i][j] > avaliable[j]) {
break;
}
}
// 不滿足則處理下一個節(jié)點進程
if (j < avaliable.length) {
continue;
} else {
// 滿足情況
// 復制會被修改的前提條件,已便于當前進程校驗不成功時,可以恢復前提條件,開始下一個節(jié)點進程的校驗
new_Avaliable = Arrays.copyOf(avaliable, avaliable.length);
new_finish = Arrays.copyOf(finish, finish.length);
// 假設當前節(jié)點進程是可以校驗成功的節(jié)點進程,修改該進程運行完畢后釋放之前分配的進程。
for (j = 0; j < new_Avaliable.length; j++) {
new_Avaliable[j] += allocation[i][j];
}
// 假設標記當前為校驗成功的安全節(jié)點進程,下一深度查找時會忽略此進程。
new_finish[i] = true;
// 增加深度
deep++;
// 以上假設為前提,進行下一深度的安全校驗判斷其他所剩余進程是否可以繼續(xù)運行,而不造成死鎖。
flog = deepCheck(new_Avaliable, allocation, need, new_finish, deep, right);
// 如果進行安全校驗后為真,說明當前進程是我們要找的進程
if (flog) {
// 保存到最終進程執(zhí)行序列的數(shù)組中
right[--deep] = i;
break;
}
}
}
}
// 安全校驗成功
if (flog) {
return true;
} else {
// 安全校驗失敗
// 清楚之前的假設標記
new_finish[right[--deep]] = false;
return false;
}
}
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
java如何將Object數(shù)組轉(zhuǎn)換為指定類型數(shù)組
這篇文章主要介紹了java如何將Object數(shù)組轉(zhuǎn)換為指定類型數(shù)組,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
Spring Boot調(diào)用 Shell 腳本實現(xiàn)看門狗功能
這篇文章主要介紹了Spring Boot調(diào)用 Shell 腳本實現(xiàn)看門狗功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
java線程并發(fā)blockingqueue類使用示例
BlockingQueue是一種特殊的Queue,若BlockingQueue是空的,從BlockingQueue取東西的操作將會被阻斷進入等待狀態(tài)直到BlocingkQueue進了新貨才會被喚醒,下面是用BlockingQueue來實現(xiàn)Producer和Consumer的例子2014-01-01
Java的數(shù)據(jù)類型和參數(shù)傳遞(詳解)
下面小編就為大家?guī)硪黄狫ava的數(shù)據(jù)類型和參數(shù)傳遞(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
Springboot之修改啟動端口的兩種方式(小結(jié))
這篇文章主要介紹了Springboot之修改啟動端口的兩種方式(小結(jié)),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09

