package com.liuyang.banker;
import java.util.Arrays;
import java.util.Collections;
import java.util.Formatter;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Banker {
/** */
/** each sum of source list */
private List<Integer> eachNumOfSrc = new LinkedList<Integer>();
/** process name and process map */
private Map<String, Process> processes = new LinkedHashMap<String, Process>();
private List<String> proIdKeys = new LinkedList<String>();
/** the current number of available source */
private List<Integer> available = new LinkedList<Integer>();
//private List<String> SrcNames = new LinkedList<String>();
/** the current safe sequence */
private List<Integer> safeSequeue = new LinkedList<Integer>();
private int numOfSrc; //资源总类数
private int numOfPro; // the number of processes
/** use the Formatter to control the format of the output */
private Formatter formatter = new Formatter(System.out);
/** 设置资源总数 */
public void setResource(String id, int assign) {
eachNumOfSrc.add(assign);
available.add(assign);
//SrcNames.add(id);
numOfSrc++;
}
/** 设置进程的 Allocation */
public void setAllocation(String id, Integer... assign) {
for(int i = 0; i < available.size(); i++) {
available.set(i, available.get(i) - assign[i]);
}
List<Integer> list = processes.get(id).getAllocation();
Collections.addAll(list, assign);
}
/** 设置进程的 Max */
public void setMax(String id, Integer... assign) {
List<Integer> maxlist = new LinkedList<Integer>();
Collections.addAll(maxlist, assign);
List<Integer> needList = new LinkedList<Integer>();
Collections.addAll(needList, assign);
Process p = new Process();
p.setMax(maxlist);
p.setNeed(needList);
processes.put(id, p);
proIdKeys.add(id);
numOfPro++;
}
/** 进程请求资源 */
public boolean request(String id, Integer... requestArray) {
Process requestProcess = processes.get(id);
if(requestProcess.isCompleted()) {
System.err.println("该进程以经完成!\n--------------------------------");
return false;
}
List<Integer> requestLink = new LinkedList<Integer>();
Collections.addAll(requestLink, requestArray);
System.out.println("请求资源:" + id + " " + requestLink);
if(isBeyondNeed(requestProcess.getNeed(), requestLink)) {
System.err.println("分配错误:分配大于所需!\n--------------------------------");
return false;
}
if(!isLarge(available, Arrays.asList(requestArray))) {
System.err.println("分配错误:可用小于请求!\n--------------------------------");
return false;
}
// is the sum resource of request equals to the need
boolean isEqualsNeed = isEqualsNeed(processes.get(id).getNeed(), requestLink);
List<Integer> allocation = requestProcess.getAllocation();
/** copy the allocation of process and available as temporary lists */
List<Integer> tempAllocation = new LinkedList<Integer>(allocation);
List<Integer> tempAvailable = new LinkedList<Integer>(available);
// tempAva 用来存放式分配后的 available.
if(isEqualsNeed) {
// flag the process to be completed.
requestProcess.setCompleted(true);
for(int i = 0; i < available.size(); i++) {
//available.set(i, tempAva.get(i));
available.set(i, available.get(i) + requestProcess.getAllocation().get(i));
allocation.set(i, 0);
}
} else {
for(int i = 0; i < available.size(); i++) {
available.set(i, available.get(i) - requestArray[i]);
allocation.set(i, allocation.get(i) + requestArray[i]);
}
}
if(!isSafe()) {
// roll back
requestProcess.setCompleted(false);
/** is not safe and roll back to the original status */
requestProcess.setAllocation(tempAllocation);
available = tempAvailable;
System.out.println("没有找到一个安全序列, 不安全, 没有分配/n--------------------------------");
describeAssigned(null, null, false);
return false;
}
describeAssigned(id, requestLink, true);
return true;
}
// 安全检查,used to terrible, maybe a little better now
/** check whether the current is safe */
public boolean isSafe() {
safeSequeue.clear();
boolean[] finish = new boolean[numOfPro];
//boolean[] isTempAssign = new boolean[numOfPro];
updateNeed();
List<Integer> tempMaxAva = new LinkedList<Integer>(available);
// god know numOfPro
for(int z = 0; z < numOfPro; z++) {
for(int i = 0; i < numOfPro; i++) {
Process p = processes.get(proIdKeys.get(i));
if(finish[i] == false) {
//updateNeed();
List<Integer> need = p.getNeed();
if(isLarge(tempMaxAva, need)) {
finish[i] = true;
if(!p.isCompleted()) safeSequeue.add(i);
updateTempMaxAva(tempMaxAva, p.getAllocation());
//isTempAssign[i] = true;
}
}
}
}
if(!isAllTrue(finish)) {
return false;
}
return true;
}
/** assert the need resource is equals to the request
* @param need resource
* @param request resource
* @return if equals return true, else return false
*/
private boolean isEqualsNeed(List<Integer> need, List<Integer> request) {
for(int i = 0; i < need.size(); i++) {
if(need.get(i) != request.get(i)) return false;
}
return true;
}
/** print the safe sequence */
private void showSafeSequence() {
for(int i = 0; i < safeSequeue.size(); i++) {
Process p = processes.get(proIdKeys.get(safeSequeue.get(i)));
if(!p.isCompleted()) System.out.print(proIdKeys.get(safeSequeue.get(i)));
}
System.out.println();
}
/** assert is the sum of request resource is beyond the sum of request
* @param need need
* @param request request
* @return return true if request is bigger than need
*/
private boolean isBeyondNeed(List<Integer> need, List<Integer> request) {
for(int i = 0; i < need.size(); i++) {
if(need.get(i) < request.get(i)) return true;
}
return false;
}
/** update all need of all processes */
private void updateNeed() {
for(int i = 0; i < numOfPro; i++) {
Process process = processes.get(proIdKeys.get(i));
for(int j = 0; j < numOfSrc; j++) {
int temp = process.getMax().get(j) - process.getAllocation().get(j);
process.getNeed().set(j, temp);
}
}
}
/** scan is there a safe sequence */
private boolean isAllTrue(boolean[] avaSequence) {
for(int i = 0; i < avaSequence.length; i++) {
if(avaSequence[i] == false) return false;
}
return true;
}
/** find a appropriate need resource and update available resource */
private void updateTempMaxAva(List<Integer> tempMaxAva, List<Integer> list) {
for(int i = 0; i < tempMaxAva.size(); i++) {
tempMaxAva.set(i, tempMaxAva.get(i) + list.get(i));
}
}
/** 判断第一个资源是否大于第二个资源 */
private boolean isLarge(List<Integer> hopeLarge, List<Integer> hopeSmall) {
for(int i = 0; i < hopeLarge.size(); i++) {
if(hopeLarge.get(i) < hopeSmall.get(i)) return false;
}
return true;
}
/** 打印分配后的状况表, use a Formatter.format is better */
private void describe() {
int space = numOfSrc*3 > 10 ? numOfSrc*3 + 3 : 15;
updateNeed();
formatter.format("\t资源情况表:\n%-8.8s %-" + space + "s %-" + space + "s %-" + space + "s\n", "Name", "Max", "Allocation", "Need");
formatter.format("%-8.8s %-" + space + "s %-" + space + "s %-" + space + "s\n", "----", "---", "----------", "----");
Set<String> set = processes.keySet();
for(Iterator<String> it = set.iterator(); it.hasNext();) {
String id = it.next();
Process process = processes.get(id);
if(!process.isCompleted()) {
formatter.format("%-8.8s %-" + space + "s %-" + space + "s %-" + space + "s\n", id, process.getMax(), process.getAllocation(), process.getNeed());
}
}
System.out.println("available:" + available);
System.out.println("-------------------------------------------------------------------------------------" +
"------------------------------------------------------------------------------------");
}
/** 打印试分配的安全序列表, use a Formatter.format is better */
private void describeAssigned(String id, List<Integer> list, boolean isRequest) {
int space = numOfSrc*3 > 17 ? numOfSrc*3 + 3 : 17;
System.out.print("找到一个安全序列为:");
showSafeSequence();
if(isRequest) System.out.println("分配了一个资源给:" + id + " " + list);
formatter.format("\t安全分配表:\n%-8.8s %-" + space + "s %-" + space + "s %-" + space + "s %-" + space + "s %-" + space + "s\n", "Name", "Max", "Allocation", "Need", "Work", "Work + Allocation");
formatter.format("%-8.8s %-" + space + "s %-" + space + "s %-" + space + "s %-" + space + "s %-" + space + "s\n", "----", "---", "----------", "----", "----", "-----------------");
List<Integer> work = null;
List<Integer> workPlusAllo = new LinkedList<Integer>(available);
for(int i = 0; i < safeSequeue.size(); i++) {
String lId = proIdKeys.get(safeSequeue.get(i));
Process process = processes.get(lId);
if(!process.isCompleted()) {
work = new LinkedList<Integer>(workPlusAllo);
for(int j = 0; j < numOfSrc; j++) {
workPlusAllo.set(j, workPlusAllo.get(j) + process.getAllocation().get(j));
}
}
if(!process.isCompleted()) {
formatter.format("%-8.8s %-" + space + "s %-" + space + "s %-" + space + "s %-" + space + "s %-" + space + "s\n", lId, process.getMax(), process.getAllocation(), process.getNeed(), work, workPlusAllo);
}
}
describe();
}
/** the entity of process, inner class */
private class Process {
private String id;
private boolean isCompleted = false;
private List<Integer> max = new LinkedList<Integer>();
private List<Integer> allocation = new LinkedList<Integer>();
private List<Integer> need = new LinkedList<Integer>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean isCompleted() {
return isCompleted;
}
public void setCompleted(boolean isCompleted) {
this.isCompleted = isCompleted;
}
public List<Integer> getMax() {
return max;
}
public void setMax(List<Integer> max) {
this.max = max;
}
public List<Integer> getAllocation() {
return allocation;
}
public void setAllocation(List<Integer> allocation) {
this.allocation = allocation;
}
public List<Integer> getNeed() {
return need;
}
public void setNeed(List<Integer> need) {
this.need = need;
}
public String toString() {
return max.toString() + allocation.toString() + need.toString();
}
}
public static void main(String[] args) {
Banker banker = new Banker();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入资源个数");
int src = scanner.nextInt();
System.out.println("请输入资源名, 资源个数, 如:\na 7\tb 8\tc 9\td 10 ...");
for(int i = 0; i < src; i++) {
String id = scanner.next();
int assign = scanner.nextInt();
banker.setResource(id, assign);
}
System.out.println("请输入进程名\t请求最大资源数\t分配资源数 如:\nA\t\t8 9 5 9\t\t5 3 4 3");
while(true) {
String name = scanner.next();
if("quit".equals(name)) break;
Integer[] maxArray = new Integer[src];
Integer[] allArray = new Integer[src];
for(int i = 0; i < src; i++) {
maxArray[i] = scanner.nextInt();
}
for(int i = 0; i < src; i++) {
allArray[i] = scanner.nextInt();
}
banker.setMax(name, maxArray);
banker.setAllocation(name, allArray);
}
if(banker.isSafe()) {
banker.describe();
banker.describeAssigned(null, null, false);
}
while(true) {
String id = scanner.next();
if("quit".equals(id)) break;
Integer[] request = new Integer[src];
for(int i = 0; i < src; i++) {
request[i] = scanner.nextInt();
}
banker.request(id, request);
}
// banker.setResource("q", 10);
// banker.setResource("w", 5);
// banker.setResource("e", 7);
// banker.setMax("A", 7, 5, 3);
// banker.setAllocation("A", 0, 1, 0);
// banker.setMax("B", 3, 2, 2);
// banker.setAllocation("B", 2, 0, 0);
// banker.setMax("C", 9, 0, 2);
// banker.setAllocation("C", 3, 0, 2);
// banker.setMax("D", 2, 2, 2);
// banker.setAllocation("D", 2, 1, 1);
// banker.setMax("E", 4, 3, 3);
// banker.setAllocation("E", 0, 0, 2);
// if(banker.isSafe()) {
// banker.describe();
// banker.describeAssigned(null, null, false);
// }
// banker.request("B", 1, 0, 2);
// System.out.println();
//
// banker.request("B", 0, 2, 0);
//
// banker.request("D", 0, 1, 0);
// banker.request("E", 4, 2, 1);
// banker.request("D", 0, 0, 1);
// banker.request("E", 0, 1, 0);
// banker.request("A", 7, 4, 3);
}
}
银行家算法(java)
原文作者:银行家问题
原文地址: https://blog.csdn.net/ora_unix/article/details/7184062
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/ora_unix/article/details/7184062
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。