银行家算法(java)


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);
	}
}


    原文作者:银行家问题
    原文地址: https://blog.csdn.net/ora_unix/article/details/7184062
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞