實驗內容
- 模擬電梯調度算法,實現對磁盤的調度。
實驗目的
- 磁盤是一種高速、大量旋轉型、可直接存取的存儲設備。它作爲計算機系統的輔助存儲器,負擔着繁重的輸入輸出任務,在多道程序設計系統中,往往同時會有若干個要求訪問磁盤的輸入輸出請示等待處理。系統可採用一種策略,儘可能按最佳次序執行要求訪問磁盤的諸輸入輸出請求,這就叫磁盤調度,使用的算法稱磁盤調度算法。磁盤調度能降低爲若干個輸入輸出請求服務所須的總時間,從而提高系統效率。本實驗要求學生模擬設計一個磁盤調度程序,觀察磁盤調度程序的動態運行過程。
實驗原理
- 模擬電梯調度算法,對磁盤調度。
磁盤是要供多個進程共享的存儲設備,但一個磁盤每個時刻只能爲一個進程服務。
當有進程在訪問某個磁盤時,其他想訪問該磁盤的進程必須等待,直到磁盤一次工作結束。
當有多個進程提出輸入輸出請求處於等待狀態,可用電梯調度算法從若干個等待訪問者中選擇一個進程,讓它訪問磁盤。當存取臂僅需移到一個方向最遠的所請求的柱面後,如果沒有訪問請求了,存取臂就改變方向。
完整代碼+測試
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());
}
}
- 結果