问题:
假设某银行有可借免息工程资助款项共10亿,现有三个工程队分别名为A队、B队、C队。每个工程队各要完成一个需5亿金额的项目,各队皆无分文,需从银行借款以完成各自的项目。各队每次从银行借部分款项以完成项目的一部分,多次借款借足所需5亿后,其项目即可顺利完工,然后再向银行归还所借5亿款项。请用银行家算法来实现上述过程,每个工程队由一线程来模拟,各队每次借款金额由一随机数来产生。
银行家算法中的数据结构:
(1) 可利用资源向量Available。这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果Available[j]=K,则表示系统中现有Rj类资源K个。
(2) 最大需求矩阵Max。这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
(3) 分配矩阵Allocation。这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。
(4) 需求矩阵Need。这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
银行家算法:
设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:
(1) 如果Requesti[j]≤Need[i,j],便转向步骤2;否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。 (2) 如果Requesti[j]≤Available[j],便转向步骤(3);否则, 表示尚无足够资源,Pi须等待。
(3) 系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值: Available[j]∶=Available[j]-Requesti[j]; Allocation[i,j]∶=Allocation[i,j]+Requesti[j]; Need[i,j]∶=Need[i,j]-Requesti[j];
(4) 系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则, 将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
代码流程图:
代码:
Bank:
package bank;
public class Bank {
private double available; //可利用资源向量
private double[] max; //最大需求矩阵,max[i]=K表示进程i需要的最大资源数目为K
private double[] allocation; //分配矩阵,allocation[i]=K表示进程i当前已分得资源数为K
private double[] need; //需求矩阵,need[i]=K表示进程i还需要K资源才能完成任务
public Bank(double available, int len, double perNeed){
//初始化
this.available = available;
max = new double[len];
allocation = new double[len];
need = new double[len];
for(int i=0; i<len; i++){
max[i] = perNeed;
allocation[i] = 0;
need[i] = perNeed;
}
}
public synchronized void request(double request, int i) throws InterruptedException {
boolean safe;
if(request<=need[i]){
if(request<=available){
available = available-request;
allocation[i] = allocation[i]+request;
need[i] = need[i]-request;
if(!testSafe()){
need[i] = need[i]+request;
allocation[i] = allocation[i]-request;
available = available+request;
System.out.println(i+"号在等待");
this.wait();
}
}else {
System.out.println(i+"号在等待");
this.wait();
}
}else {
System.out.println("出错");
}
}
public synchronized void back(double money){
available = available+money;
System.out.println("收到还钱");
this.notifyAll();
}
private boolean testSafe() {
for(int i=0; i<max.length; i++){
if(need[i]<available){
return true;
}
}
return false;
}
}
Start:
package bank;
public class Start {
public static void main(String[] args){
Semaphore semaphore = new Semaphore(1);
double need = 5;
int len = 3;
Team[] teams = new Team[3];
Bank bank = new Bank(10, len, need);
teams[0] = new Team("A队",5,semaphore, bank, 0);
teams[1] = new Team("B队",5,semaphore, bank, 1);
teams[2] = new Team("C队",5,semaphore, bank, 2);
new Thread(teams[0]).start();
new Thread(teams[1]).start();
new Thread(teams[2]).start();
}
}
Team:
package bank;
import java.text.DecimalFormat;
import java.util.Random;
public class Team implements Runnable{
private String teamName;
private double count;
private double need; //需要资源的总数
private Semaphore semaphore;
private Bank bank;
private int number;
public Team(String teamName, double count, Semaphore semaphore, Bank bank, int number) {
this.teamName = teamName;
this.count = count;
this.need = count;
this.semaphore = semaphore;
this.bank = bank;
this.number = number;
}
public double getNeed(){
return this.need;
}
@Override
public void run() {
Random random = new Random();
while (true) {
double money = random.nextDouble()*5;//得到一个0~5的随机浮点数
if(money>need){
money = need;
}
try {
Thread.sleep((int)(money)*1000);
bank.request(money, number);
System.out.print(teamName+"成功借了"+money+"个亿!");
need-=money;
System.out.println("还需"+need+"亿即可还钱");
if(need == 0){
bank.back(count);
System.out.println(teamName+"还了"+count+"亿");
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行效果: