文章目录

  • 实验内容
  • 实验目的
  • 实验原理
  • 完整代码+测试


实验内容

  • 模拟电梯调度算法,实现对磁盘的调度。

实验目的

  • 磁盘是一种高速、大量旋转型、可直接存取的存储设备。它作为计算机系统的辅助存储器,负担着繁重的输入输出任务,在多道程序设计系统中,往往同时会有若干个要求访问磁盘的输入输出请示等待处理。系统可采用一种策略,尽可能按最佳次序执行要求访问磁盘的诸输入输出请求,这就叫磁盘调度,使用的算法称磁盘调度算法。磁盘调度能降低为若干个输入输出请求服务所须的总时间,从而提高系统效率。本实验要求学生模拟设计一个磁盘调度程序,观察磁盘调度程序的动态运行过程。

实验原理

  • 模拟电梯调度算法,对磁盘调度。
    磁盘是要供多个进程共享的存储设备,但一个磁盘每个时刻只能为一个进程服务。
    当有进程在访问某个磁盘时,其他想访问该磁盘的进程必须等待,直到磁盘一次工作结束。
    当有多个进程提出输入输出请求处于等待状态,可用电梯调度算法从若干个等待访问者中选择一个进程,让它访问磁盘。当存取臂仅需移到一个方向最远的所请求的柱面后,如果没有访问请求了,存取臂就改变方向。

完整代码+测试

import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

//这是一个磁头里面描述此时他在哪个下标 并且是往左方向走还是右方向
class Head {
    public int index;
    public String direction;

    public Head(int index, String direction) {
        this.index = index;
        this.direction = direction;
    }
}

//这是描述一个访问磁道任务的一个类
class MyRunnable implements Runnable {

    //要访问的磁道
    public int track;
    public boolean key = true;

    public MyRunnable(int track) {
        this.track = track;
    }

    @Override
    public void run() {
        System.out.print(track + " ");
    }
}

public class DiskScheduling extends Thread {

    //需要一个链表去存储去存储要访问磁盘的线程
    //一个count记录访问次数
    //sum去记录访问距离
    //还需要一个磁头
    //还需要一个最大磁道是多少
    private List<MyRunnable> threadList = new LinkedList<>();
    private int count;
    private int sum;
    private Head head;
    public static final int MaximumTrack = 200;

    //在构造函数里初始化磁头
    public DiskScheduling(int index, String direction) {
        this.head = new Head(index, direction);
    }

    //需要一个方法往链表为添加程序
    public void add(int[] tracks) throws InterruptedException {

        //创建线程 线程的名字就是他有寻找的磁道地址

        for (int track : tracks
             ) {
            MyRunnable myRunnable = new MyRunnable(track);
            threadList.add(myRunnable);
        }


        //将链表按要寻道的地址进行排序
       threadList.sort(new Comparator<MyRunnable>() {
           @Override
           public int compare(MyRunnable o1, MyRunnable o2) {
               return o1.track - o2.track;
           }
       });

        this.start();
        this.join();
        //worke();
    }

    @Override
    public void run() {

        while (this.count != threadList.size()) {
            while (this.head.direction.equals("right")) {

                for (MyRunnable m : threadList
                        ) {
                    if (m.track >= head.index && m.key) {
                        count++;
                        int distance = m.track - this.head.index;
                        sum += distance;
                        this.head.index = m.track;
                        m.key = false;
                        m.run();
                        //threadList.remove(m);
                    }
                    this.head.direction = "left";
                }

            }


            while (this.head.direction.equals("left")) {

                for (int i = threadList.size() - 1; i >= 0; i--) {

                    if (threadList.get(i).track > this.head.index || !threadList.get(i).key) {
                        continue;
                    }

                    //此时表示找到了比现在下标小的
                    this.count++;
                    int distance = this.head.index - threadList.get(i).track;
                    sum += distance;
                    this.head.index = threadList.get(i).track;
                    threadList.get(i).key = false;
                    this.threadList.get(i).run();
                    //this.threadList.remove(this.threadList.get(i));
                }

                this.head.direction = "right";
            }
        }
    }

    /* //需要一个方法去执行程序
    private void worke() throws InterruptedException {

        while (! this.threadList.isEmpty()) {

            while (this.head.direction.equals("right")) {
                synchronized (this) {
                    for (Thread t : this.threadList
                    ) {
                        if (Integer.parseInt(t.getName()) > this.head.index) {
                            this.count++;
                            int distance = Integer.parseInt(t.getName()) - this.head.index;
                            sum += distance;
                            this.head.index = Integer.parseInt(t.getName());
                            t.start();
                            t.join();
                            this.threadList.remove(t);
                        }
                    }
                }
                this.head.direction = "left";
            }

            while (this.head.direction.equals("left")) {
                synchronized (this) {
                    for (int i = this.threadList.size() - 1; i >= 0; i--) {
                        if (Integer.parseInt(this.threadList.get(i).getName()) > this.head.index) {
                            continue;
                        }

                        //此时表示找到了比现在下标小的
                        this.count++;
                        int distance = this.head.index - Integer.parseInt(this.threadList.get(i).getName());
                        sum += distance;
                        this.head.index = Integer.parseInt(this.threadList.get(i).getName());
                        this.threadList.get(i).start();
                        this.threadList.get(i).join();
                        this.threadList.remove(this.threadList.get(i));
                    }
                }
                this.head.direction = "right";
            }

        }
    }*/

    //需要一个方法返回平均寻道长度
    public float averageSeekLength () {

        return (float) ((this.sum * 1.0) / this.count);
    }
}
  • 测试
    假设磁盘有200个磁道,用C语言随机函数随机生成一个磁道请求序列(不少于15个)放入模拟的磁盘请求队列中,假定当前磁头在100号磁道上,并向磁道号增加的方向上移动。请给出按电梯调度算法进行磁盘调度时满足请求的次序,并计算出它们的平均寻道长度。
import java.util.Arrays;
import java.util.Random;

public class DiskTest {

    public static void main(String[] args) throws InterruptedException {

        //需要在创建磁盘调度的时候说明此时磁头的位置和方向
        DiskScheduling diskScheduling = new DiskScheduling(100, "right");

        //生成15个随机数
        int[] nums = new int[15];
        for (int i = 0; i < 15; i++) {
            Random random = new Random();
            nums[i] = random.nextInt(DiskScheduling.MaximumTrack);
        }

        System.out.println("初始申请序列:");
        System.out.println(Arrays.toString(nums));

        System.out.println("=========================");

        System.out.println("电梯调度执行顺序");
        diskScheduling.add(nums);

        System.out.println();
        //等线程执行完毕再去打印寻道
        diskScheduling.join();
        System.out.print("平均寻道为:");
        System.out.println(diskScheduling.averageSeekLength());
    }
}
  • 结果