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

