操作系统 磁盘调度算法 JAVA语言设计程序 模拟 先来先服务FCFS,最短寻道时间优先SSTF,扫描SCAN,循环扫描SCAN算法的工作过程 及平均寻道长度

问题描述:

设计程序模拟先来先服务FCFS,最短寻道时间优先SSTF,SCAN和循环SCAN算法的工作过程。假设有n个磁道号所组成的磁道访问序列,给定开始磁道号m和磁头移动的方向(正向或者反向),分别利用不同的磁盘调度算法访问磁道序列,给出每一次访问的磁头移动距离,计算每种算法的平均寻道长度。

程序要求如下:

1)利用先来先服务FCFS,最短寻道时间优先SSTF,SCAN和循环SCAN算法模拟磁道访问过程。

2)模拟四种算法的磁道访问过程,给出每个磁道访问的磁头移动距离。

3)输入:磁道个数n和磁道访问序列,开始磁道号m和磁头移动方向(对SCAN和循环SCAN算法有效),算法选择1-FCFS,2-SSTF,3-SCAN,4-循环SCAN。

4)输出:每种算法的平均寻道长度。


例题:当前磁头停在100号磁道,有15个磁道请求先后到达,依次为64,117, 305,72,166,288,193,11,102,219,95,321,35,146,188,计算FCFS,SSTF,SCAN(向里), CSCAN(向外),这四种算法的平均寻道长度。


package HomeWork_OS.DiskSchedulingAlgorithm;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class disk_Algorithm {

    static int totleDistance = 0; //总移动磁道数
    static int totleDisk = 0;      //总磁盘数


    //平均寻道长度
    public static void avgSeekTime(int totleDistance, int totleDisk) {
        double avgSeekTime = (double) totleDistance / totleDisk;//平均寻道时间
        System.out.println("平均寻道长度: " + String.format("%.4f", avgSeekTime) + "\n");

    }

    /*先来先服务FCFS*/
    public static void FCFS(int[] arr, int head) {//磁道抵达数组,当前停留磁头号
        totleDisk = arr.length;//获得总磁盘数
        totleDistance = 0;//清空总磁道移动距离
        //新建一个二维数组存访问的磁道号和移动距离
        int[][] resultArr = new int[arr.length][2];
        //设置一个存储当前磁头号的标识
        int diskNo = head;
        //遍历磁道抵达数组
        for (int i = 0; i < arr.length; i++) {
            resultArr[i][0] = arr[i];
            resultArr[i][1] = (int) Math.abs(arr[i] - diskNo);
            diskNo = resultArr[i][0];
        }
        System.out.println("访问磁道号" + "\t\t移动距离<磁道数>");
        for (int i = 0; i < resultArr.length; i++) {
            System.out.println(resultArr[i][0] + "\t\t\t\t" + resultArr[i][1]);
            totleDistance += resultArr[i][1];
        }
        avgSeekTime(totleDistance, totleDisk);
    }

    /*最短寻道时间优先SSTF*/
    public static void SSTF(int[] arr, int head) {
        totleDisk = arr.length;//获得总磁盘数
        totleDistance = 0;//清空总磁道移动距离
        //新建一个链表用来存储磁道号的数组
        List diskList = new LinkedList();
        //将磁道号数组,存入链表
        for (int i : arr) {
            diskList.add(i);
        }
//        System.out.println(diskList);
        System.out.println("访问磁道号" + "\t\t移动距离<磁道数>");
        for (int i = 0; i < arr.length; i++) {
            //最小移动距离,初始为当前磁头号到链表中第一个元素的绝对值
            int minDistance = Math.abs(head - (int) diskList.get(0));
            //最小移动距离的磁道号,初始值为链表中第一个元素
            int minDiskNo = (int) diskList.get(0);
            //链表中最小移动距离磁道号索引
            int removeIndex = 0;
            //遍历链表,找出离当前磁头最近的磁道号
            for (int size = diskList.size(), j = 0; j < size; j++) {
                if (minDistance > (int) Math.abs(head - (int) diskList.get(j))) {
                    minDistance = (int) Math.abs(head - (int) diskList.get(j));
                    minDiskNo = (int) diskList.get(j);
                    removeIndex = j;
                }
            }
            totleDistance += minDistance;
            //将头节点设为目前最小运动距离磁道号->头节点移动到当前最小移动距离磁道号
            head = minDiskNo;
            //从链表中移除最小移动距离的磁道号
            diskList.remove(removeIndex);
            System.out.println(minDiskNo + "\t\t\t\t" + minDistance);
//            System.out.println(diskList);
        }
        avgSeekTime(totleDistance, totleDisk);
    }

    /*扫描SCAN算法*/
    public static void SCAN(int[] arr, int head, boolean flag) { //flag传入方向 true->1外向 false->0里向(向外为磁道号增大的方向移动)
   /*     System.out.println("===============");
        System.out.println("head: " + head);
        System.out.println("flag: " + flag);*/
        totleDisk = arr.length;//获得总磁盘数
        totleDistance = 0;//清空总磁道移动距离
        //新建一个链表用来存储磁道号的数组
        List diskList = new LinkedList();
        for (int i : arr) {
            diskList.add(i);
        }
        //给链表排序(从小到大排序)
        Collections.sort(diskList);
        System.out.println(diskList);

        //链表中最小移动距离磁道号索引
        int index = 0;
        //遍历链表
        for (int size = diskList.size(), j = 0; j < size; j++) {
            //根据需要寻道的方向,找到离当前磁道号最近的磁道
            if ((int) diskList.get(j) == head) {
                index = j;
                break;//结束循环
            } else if ((int) diskList.get(j) >= head) { //找出head右侧最近的磁道号
                index = j;
                break;

            }else if(j == size -1){
                index = j;
                break;
            }
        }
        //移动距离,初始为当前磁头号到链表中第一个元素的绝对值
        int distance;
        int size = diskList.size();
        System.out.println("访问磁道号" + "\t\t移动距离<磁道数>");
        if (flag) {
            for (int j = 0; j < size - index; j++) {
                distance = Math.abs(head - (int)diskList.get(index + j));
                totleDistance += distance;
                head = (int)diskList.get(index + j);
                System.out.println((int) diskList.get(index + j) + "\t\t\t\t" + distance);
            }
            for (int j = index - 1; j >= 0; j--) {
                distance = Math.abs(head - (int)diskList.get(j));
                totleDistance += distance;
                head = (int)diskList.get(j);
                System.out.println((int) diskList.get(j) + "\t\t\t\t" + distance);
            }

        } else {
            //当当前磁头号恰好在要扫描的磁道上时,或着当前磁头号大于要扫描的所有磁道号
            if ((int)diskList.get(index) == head || index == diskList.size() - 1){
                System.out.println("index: " + index);
                for (int j = index; j >= 0; j--) {
                    distance = Math.abs(head - (int)diskList.get(j));
                    totleDistance += distance;
                    head = (int)diskList.get(j);
                    System.out.println((int) diskList.get(j) + "\t\t\t\t" + distance);
                }
                for (int j = 1; j < size - index; j++) {
                    distance = Math.abs(head - (int)diskList.get(index + j));
                    totleDistance += distance;
                    head = (int)diskList.get(index + j);
                    System.out.println((int) diskList.get(index + j) + "\t\t\t\t" + distance);
                }

            } else {
                System.out.println("index: " + index);
                for (int j = index - 1; j >= 0; j--) {
                    distance = Math.abs(head - (int)diskList.get(j));
                    totleDistance += distance;
                    head = (int)diskList.get(j);
                    System.out.println((int) diskList.get(j) + "\t\t\t\t" + distance);
                }
                for (int j = 0; j < size - index ; j++) {
                    distance = Math.abs(head - (int)diskList.get(index + j));
                    totleDistance += distance;
                    head = (int)diskList.get(index + j);
                    System.out.println((int) diskList.get(index + j) + "\t\t\t\t" + distance);
                }
            }
        }
        avgSeekTime(totleDistance,totleDisk);
    }



    /*循环扫描CSCAN*/
    public static void CSCAN(int[] arr, int head, boolean flag) { //flag传入方向 true->1向外 false->0向里
/*        System.out.println("===============");
        System.out.println("head: " + head);
        System.out.println("flag: " + flag);*/
        totleDisk = arr.length;//获得总磁盘数
        totleDistance = 0;//清空总磁道移动距离
        //新建一个链表用来存储磁道号的数组
        List diskList = new LinkedList();
        for (int i : arr) {
            diskList.add(i);
        }
        //给链表排序(从小到大排序)
        Collections.sort(diskList);
        System.out.println(diskList);
        //链表中最小移动距离磁道号索引
        int index = 0;
        //遍历链表
        for (int size = diskList.size(), j = 0; j < size; j++) {
            //根据需要寻道的方向,找到离当前磁道号最近的磁道
            if ((int) diskList.get(j) == head) {
                index = j;
                break;//结束循环
            } else if ((int) diskList.get(j) >= head) { //找出head右侧最近的磁道号
                index = j;
                break;
            }else if(j == size -1){
                index = j;
                break;
            }
        }
        //移动距离,初始为当前磁头号到链表中第一个元素的绝对值
        int distance;
        int size = diskList.size();
//        System.out.println("index: " + index);
        System.out.println("访问磁道号" + "\t\t移动距离<磁道数>");
        if (flag) {
            if ((int) diskList.get(index) < head)
                index = 0;
            for (int j = 0; j < size - index; j++) {
                distance = Math.abs(head - (int)diskList.get(index + j));
                totleDistance += distance;
                head = (int)diskList.get(index + j);
                System.out.println((int) diskList.get(index + j) + "\t\t\t\t" + distance);
            }
            for (int j = 0; j < index; j++) {
                distance = Math.abs(head - (int)diskList.get(j));
                totleDistance += distance;
                head = (int)diskList.get(j);
                System.out.println((int) diskList.get(j) + "\t\t\t\t" + distance);
            }

        } else {
            //当当前磁头号恰好在要扫描的磁道上时,或着当前磁头号大于要扫描的所有磁道号
            if ((int) diskList.get(index) > head && index != 0)
                index = index - 1;

//            System.out.println("index: " + index);
            for (int j = index; j >= 0; j--) {
                distance = Math.abs(head - (int)diskList.get(j));
                totleDistance += distance;
                head = (int)diskList.get(j);
                System.out.println((int) diskList.get(j) + "\t\t\t\t" + distance);
            }
            for (int j = size - 1; j > index ; j--) {
                distance = Math.abs(head - (int)diskList.get(j));
                totleDistance += distance;
                head = (int)diskList.get(j);
                System.out.println((int) diskList.get(j) + "\t\t\t\t" + distance);
            }

        }
        avgSeekTime(totleDistance,totleDisk);
    }


    public static void main(String[] args) {
        /*测试用例一
        * 9
        * 55 58 39 18 90 160 150 38 184
        * 100
        * */
        /*测试用例二
        * 15
        * 64 117 305 72 166 288 193 11 102 219 95 321 35 146 188
        * 100
        * */
        Scanner sc = new Scanner(System.in);
        boolean flag = true;
        System.out.print("请输入提出磁盘I/O申请的进程数: ");
        int inputDiskNum = sc.nextInt(); //用户键盘输入进程数
        int[] diskArr = new int[inputDiskNum];
        System.out.print("请依次输入要访问的磁道号: ");
        for (int i = 0; i < diskArr.length; i++) {
            diskArr[i] = sc.nextInt();
        }
        System.out.print("请输入开始的磁道号: ");
        int inputDiskHead = sc.nextInt();
        int userOption;

        boolean direction;
        while (flag) {
            System.out.print("请选择寻道方式: " +
                    "\n1——FCFS 2——SSTF 3——SCAN 4——CSCSN: ");
            userOption = sc.nextInt();
            switch (userOption) {
                case 1:
                    FCFS(diskArr, inputDiskHead);
                    System.out.print("是否继续选择寻道算法? 1——是 0——否: ");
                    flag = sc.nextInt() > 0 ? true : false;
                    break;
                case 2:
                    SSTF(diskArr, inputDiskHead);
                    System.out.print("是否继续选择寻道算法? 1——是 0——否: ");
                    flag = sc.nextInt() > 0 ? true : false;
                    break;
                case 3:
                    System.out.print("请选择开始方向: 1——向外 0——向里: ");
                    direction = sc.nextInt() > 0 ? true : false;
                    SCAN(diskArr, inputDiskHead, true);

                    System.out.print("是否继续选择寻道算法? 1——是 0——否: ");
                    flag = sc.nextInt() > 0 ? true : false;
                    break;
                case 4:
                    System.out.print("请选择开始方向: 1——向外 2——向里: ");
                    direction = ((sc.nextInt() > 0) ? true : false);
                    CSCAN(diskArr, inputDiskHead, true);

                    System.out.print("是否继续选择寻道算法? 1——是 0——否: ");
                    flag = sc.nextInt() > 0 ? true : false;
                    break;
                default:
                    System.out.println("输入有误,请重新输入! ");
                    break;
            }
            System.out.println( flag ? "" : "成功退出程序!!");
        }



//        int[] diskArr = new int[]{64, 117, 305, 72, 166, 288, 193, 11, 102, 219, 95, 321, 35, 146, 188};
//        FCFS(diskArr, 100);
//        SSTF(diskArr, 100);
//        SCAN(diskArr, 100, true);
//        CSCAN(diskArr, 100, true);


        /*测试用例*/
/*        int[] testArr = new int[]{55, 58, 39, 18, 90, 160, 150, 38, 184};
        FCFS(testArr, 100);
        SSTF(testArr, 100);
        SCAN(testArr, 100, true);
        CSCAN(testArr, 100, true);

        FCFS(testArr,100);
        SSTF(testArr, 100);
        SCAN(testArr,100,true);
        SCAN(testArr,100,false);

        SCAN(testArr,10,true);
        SCAN(testArr,10,false);
        SCAN(testArr,18,false);
        SCAN(testArr,18,true);
        SCAN(testArr,200,false);
        SCAN(testArr,200,true);
        SCAN(testArr,160,false);
        SCAN(testArr,160,true);

        CSCAN(testArr,10,true);
        CSCAN(testArr,100,true);
        CSCAN(testArr,160,true);
        CSCAN(testArr,200,true);
        CSCAN(testArr,10,false);
        CSCAN(testArr,100,false);
        CSCAN(testArr,160,false);
        CSCAN(testArr,200,false);
        CSCAN(testArr,19,false);*/



    }
}

运行截图:

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值