使用java实现银行家算法

 更新时间:2019年12月26日 11:37:44   作者:demo易  
这篇文章主要为大家详细介绍了如何使用java实现银行家算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

银行家算法核心

先寻找满足系统当前剩余的资源量(avaliable )>=进程运行所需的资源数的进程(need),再假设这个进程安全校验是成功的,当这个进程运行完毕后,释放资源后,现在系统当前剩余的资源(avaliable)=avaliable+该线程之前已分配的资源(allocation) ,将该节点进程设为处理时忽略进程,再以上条件为前提进行安全校验。
安全校验:一个进程获得资源后,运行完毕,释放之前分配的资源,其他的线程可以继续运行,而不会造成死锁。
这样就会产生回溯。

满足条件:是否存在一个进程运行所需的资源数<=当前系统剩余的资源数。

查找操作:先判断回溯的步长(层数)是否等于节点的个数,如果等于说明已经找到了正确路径,返回真给上一层,如果不满足,则看一下此层是否存在满足条件的节点,如果存在,这一该节点为回溯点开始查找操作。如果都不存在,说明上一层的回溯点不是我们要找的节点,返回假给上一层,并回溯回到上一层节点,将忽略标记清楚,换另一个满足条件的节点继续在进行查找操作。

先以一个满足条件的节点进行忽略标记(下一次查找时可忽略此节点),回溯的步长加一,再进行查找操作(下一层)。

import java.util.Arrays;

public class BanksTest {
  // 用于存储预操作后的资源变化
  static int[] new_Avaliable = null;
  // 用于存储预操作的完成度
  static boolean[] new_finish = null;
  // 用于保存最终的进程执行顺序,初始化为非法进程-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 } };
    // 当前系统可用资源量
    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];
      }
    }
    // 创建递归深度
    int deep = 0;
    // 调用回溯递归算法
    deepCheck(avaliable, allocation, need, finish, deep, right);
    int i = 0;
    // 查看最终的安全序列的值,看是否存在初始的非法进程,如果存在,则说明该案例不存在安全的进程执行顺序
    for (; i < right.length; i++) {
      if (right[i] == -1) {
        break;
      }
    }
    if (i < right.length) {
      System.out.println("该案例不存在安全的进程执行顺序");
      return;
    }
    // 打印安全的执行顺序
    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;
    // 如果深度为进程的个数数说明已经查找到头了,说明上一深度的进程是安全节点。因为上一深度的进程满足了当前资源数大于或等于该进程运行所需的资源数,且为安全序列中最后一个节点。
    if (deep == need.length) {
      return true;
    }
    // 遍历所有节点进程开始查找,直到找到安全校验成功的的节点进程
    for (int i = 0; i < need.length; i++) {
      // 对于未被标记的进行校验,已被标记的为已被列为安全节点所以无需再进行校验
      if (!finish[i]) {
        // 判断当前的节点进程的剩余的资源量,是否满足运行所需的资源量
        for (j = 0; j < avaliable.length; j++) {
          // 不满足
          if (need[i][j] > avaliable[j]) {
            break;
          }
        }
        // 不满足则处理下一个节点进程
        if (j < avaliable.length) {
          continue;
        } else {
          // 满足情况
          // 复制会被修改的前提条件,已便于当前进程校验不成功时,可以恢复前提条件,开始下一个节点进程的校验
          new_Avaliable = Arrays.copyOf(avaliable, avaliable.length);
          new_finish = Arrays.copyOf(finish, finish.length);
          // 假设当前节点进程是可以校验成功的节点进程,修改该进程运行完毕后释放之前分配的进程。
          for (j = 0; j < new_Avaliable.length; j++) {
            new_Avaliable[j] += allocation[i][j];
          }
          // 假设标记当前为校验成功的安全节点进程,下一深度查找时会忽略此进程。
          new_finish[i] = true;
          // 增加深度
          deep++;
          // 以上假设为前提,进行下一深度的安全校验判断其他所剩余进程是否可以继续运行,而不造成死锁。
          flog = deepCheck(new_Avaliable, allocation, need, new_finish, deep, right);
          // 如果进行安全校验后为真,说明当前进程是我们要找的进程
          if (flog) {
            // 保存到最终进程执行序列的数组中
            right[--deep] = i;
            break;
          }

        }

      }

    }
    // 安全校验成功
    if (flog) {
      return true;
    } else {
      // 安全校验失败
      // 清楚之前的假设标记
      new_finish[right[--deep]] = false;
      return false;
    }

  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java实现过滤掉map集合中key或value为空的值示例

    Java实现过滤掉map集合中key或value为空的值示例

    这篇文章主要介绍了Java实现过滤掉map集合中key或value为空的值,涉及java针对map的简单遍历、判断、移除等相关操作技巧,需要的朋友可以参考下
    2018-06-06
  • 最新IntelliJ IDEA 2022配置 Tomcat 8.5 的详细步骤演示

    最新IntelliJ IDEA 2022配置 Tomcat 8.5 的详细步骤演示

    这篇文章主要介绍了IntelliJ IDEA 2022 详细配置 Tomcat 8.5 步骤演示,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • Java详细介绍单例模式的应用

    Java详细介绍单例模式的应用

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
    2022-09-09
  • Java 控制流程、大数值、数组

    Java 控制流程、大数值、数组

    这篇文章主要给大家介绍的是Java 控制流程、大数值、数组的一些相关自来哦,感兴趣的小伙伴可以参考下面文章的具体内容,希望文章对你有所帮助
    2021-10-10
  • Java JVM虚拟机运行机制

    Java JVM虚拟机运行机制

    JVM(Java虚拟机)一种用于计算设备的规范,可用不同的方式(软件或硬件)加以实现。接下来通过本文给大家简单介绍Java JVM虚拟机运行机制,感兴趣的朋友一起看看吧
    2017-03-03
  • Java并发编程之ConcurrentLinkedQueue解读

    Java并发编程之ConcurrentLinkedQueue解读

    这篇文章主要介绍了Java并发编程之ConcurrentLinkedQueue解读,非阻塞的实现方式则可以使用循环CAS的方式来实现,而ConcurrentLinkedQueue就是juc包中自带的经典非堵塞方式实现的工具类,需要的朋友可以参考下
    2023-12-12
  • Java的Hello World详解

    Java的Hello World详解

    当我们学习一门编程语言的时候,我们都会先学如何输出Hello World!本文通过几个例子给大家介绍输出Hello World的代码,感兴趣的朋友一起看看吧
    2021-09-09
  • Java对数组实现选择排序算法的实例详解

    Java对数组实现选择排序算法的实例详解

    这篇文章主要介绍了Java对数组实现选择排序算法的实例,选择排序的比较次数为 O(N^2)而交换数为O(N),需要的朋友可以参考下
    2016-04-04
  • Java使用easyExcel批量导入数据详解

    Java使用easyExcel批量导入数据详解

    这篇文章主要介绍了Java使用easyExcel批量导入数据详解,通常我们会提供一个模板,此模块我们可以使用easyExcel导出数据生成的一个Excel文件当作模板,提供下载链接,用户在该文件内填入规定的数据格式以后可以批量导入数据到数据库中,需要的朋友可以参考下
    2023-08-08
  • 浅谈JVM之类的加载链接和初始化

    浅谈JVM之类的加载链接和初始化

    有了java class文件之后,为了让class文件转换成为JVM可以真正运行的结构,需要经历加载,链接和初始化的过程。这三个过程是怎么工作的呢?在本文中你将会找到答案。
    2021-06-06

最新评论