package com.raylew.algorithm.os;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;
/**
* Created by [Ray Lew] on 2015/7/16
* QQ:897929321
* site:http://raylew.info
* mail:aishangzoulu@gmail.com
*/
/*
一种磁盘访问调度算法-移臂调度算法包括以下四种:
1) 先来先服务算法; (根据访问者提出访问请求的先后次序来决定执行次序。
2) 最短寻找时间优先调度算法;(从等待的访问者中挑选寻找时间最短的那个请求执行,而不管访问者的先后次序。
3) 电梯调度算法;(从移动臂当前位置沿移动方向选择最近的那个柱面的访问者来执行,若该方向上无请求访问时,就改变移动方向再选择。)
4) 单向扫描调度算法。 (从0柱面开始往里单向扫描,扫到哪个执行哪个。
*/
public class ElevatorSchedule {
public static void main(String[] args) {
Disk disk = new Disk();
System.out.println("系统功能菜单:");
System.out.println("1.接收请求");
System.out.println("2.驱动调度");
System.out.println("3.退出系统");
Scanner scanner = new Scanner(System.in);
int mark = scanner.nextInt();
while (mark != 3) {
switch (mark) {
case 1:
receiveReq(disk);
break;
case 2:
driver_scheduling(disk);
break;
}
System.out.println("请输入指令:");
mark = scanner.nextInt();
}
System.out.println("已退出");
}
/**
* 接收请求
*
* @param disk
*/
public static void receiveReq(Disk disk) {
LinkedList<IOTableNode> iotable = disk.getIotable();
System.out.println("请输入进程信息:");
Scanner scanner = new Scanner(System.in);
String p_name = scanner.next();
Integer cylinder = scanner.nextInt();
Integer track = scanner.nextInt();
Integer phy_record = scanner.nextInt();
IOTableNode node = new IOTableNode(p_name, cylinder, track, phy_record);
iotable.add(node);
System.out.println("接收请求成功");
}
/**
* 驱动调度
*
* @param disk
*/
public static void driver_scheduling(Disk disk) {
LinkedList<IOTableNode> iotable = disk.getIotable();
if (iotable.isEmpty()) {
System.out.println("没有请求");
return;
} else {
disk.printIOTable();
disk.schedule();// 驱动调度
}
}
}
class IOTableNode {
private String p_name;// 进程名
private Integer cylinder;// 柱面
private Integer track;// 磁道
private Integer phy_record;// 物理记录
public IOTableNode() {
}
public IOTableNode(String p_name, Integer cylinder, Integer track,
Integer phy_record) {
super();
this.p_name = p_name;
this.cylinder = cylinder;
this.track = track;
this.phy_record = phy_record;
}
public String getP_name() {
return p_name;
}
public void setP_name(String p_name) {
this.p_name = p_name;
}
public Integer getCylinder() {
return cylinder;
}
public void setCylinder(Integer cylinder) {
this.cylinder = cylinder;
}
public Integer getTrack() {
return track;
}
public void setTrack(Integer track) {
this.track = track;
}
public Integer getPhy_record() {
return phy_record;
}
public void setPhy_record(Integer phy_record) {
this.phy_record = phy_record;
}
}
class Disk {
private Integer cur_cylinder;// 当前柱面
private Integer cur_track;// 当前磁道
private boolean cur_direction;// 当前移臂臂方向,true表示向里
private Integer cur_phy_record;// 当前物理记录
private LinkedList<IOTableNode> iotable;
public Disk() {
cur_cylinder = 0;// 柱面号为0
cur_phy_record = 0;
cur_track = 0;
cur_direction = true;// 方向向里
iotable = new LinkedList<IOTableNode>();
initIOTable();
}
public void initIOTable() {
IOTableNode n0 = new IOTableNode("0", 0, 0, 0);
IOTableNode n1 = new IOTableNode("1", 1, 1, 1);
IOTableNode n2 = new IOTableNode("2", 1, 10, 5);
IOTableNode n3 = new IOTableNode("3", 1, 5, 4);
IOTableNode n4 = new IOTableNode("4", 10, 5, 7);
IOTableNode n5 = new IOTableNode("5", 5, 11, 6);
IOTableNode n6 = new IOTableNode("6", 6, 11, 6);
IOTableNode n7 = new IOTableNode("7", 10, 4, 7);
IOTableNode n8 = new IOTableNode("8", 1, 2, 0);
iotable.add(n0);
iotable.add(n1);
iotable.add(n2);
iotable.add(n3);
iotable.add(n4);
iotable.add(n5);
iotable.add(n6);
iotable.add(n7);
iotable.add(n8);
}
/**
* 电梯调度
*/
public void schedule() {
boolean samecylinder = false;
for (Iterator iterator = iotable.iterator(); iterator.hasNext(); ) {
IOTableNode node = (IOTableNode) iterator.next();
if (node.getCylinder() == cur_cylinder) {
samecylinder = true;
break;
}
}
if (samecylinder) {
int index = 0;
index = selectPhy_record();
IOTableNode selected = iotable.remove(index);
System.out.println("当前选中了进程:" + selected.getP_name() + ",柱面:"
+ selected.getCylinder() + ",物理记录号:"
+ selected.getPhy_record() + ",移臂方向:" + "同一柱面没有移臂");
} else {
IOTableNode selected = null;
if (cur_direction) {// 方向向里
LinkedList<IOTableNode> reslist = judge(1);
if (reslist.isEmpty()) {// 没有大于当前柱面的请求
this.setCur_direction(false);// 修改方向向外
selected = selectCylinder(0, iotable);
} else {
selected = selectCylinder(1, reslist);
}
iotable.remove(selected);
this.setCur_cylinder(selected.getCylinder());
this.setCur_track(selected.getTrack());
this.setCur_phy_record(selected.getPhy_record());
String direction = cur_direction ? "向里" : "向外";
System.out.println("当前选中了进程:" + selected.getP_name() + ",柱面:"
+ selected.getCylinder() + ",物理记录号:"
+ selected.getPhy_record() + ",移臂方向:" + direction);
} else {// 方向向外
LinkedList<IOTableNode> reslist = judge(0);
if (reslist.isEmpty()) {// 没有小于当前柱面的请求
selected = selectCylinder(1, iotable);
this.setCur_direction(true);// 修改方向向里
} else {
selected = selectCylinder(0, reslist);
}
iotable.remove(selected);
this.setCur_cylinder(selected.getCylinder());
this.setCur_track(selected.getTrack());
this.setCur_phy_record(selected.getPhy_record());
String direction = cur_direction ? "向里" : "向外";
System.out.println("当前选中了进程:" + selected.getP_name() + ",柱面:"
+ selected.getCylinder() + ",物理记录号:"
+ selected.getPhy_record() + ",移臂方向:" + direction);
}
}
}
/**
* 同一柱面选择磁道近的
*
* @return
*/
public int selectPhy_record() {
int min = Integer.MAX_VALUE;
int index = 0;
for (int i = 0; i < iotable.size(); i++) {
IOTableNode node = (IOTableNode) iotable.get(i);
if (node.getCylinder() == cur_cylinder) {
if (Math.abs(node.getPhy_record() - cur_phy_record) < min) {
min = Math.abs(node.getPhy_record() - cur_phy_record);
index = i;
}
}
}
return index;
}
/**
* 判断是否有比当前柱面大或者小的请求
*
* @param mark 1表示是否有大于
* @return
*/
public LinkedList<IOTableNode> judge(int mark) {
LinkedList<IOTableNode> reslist = new LinkedList<IOTableNode>();
if (mark == 1) {
for (int i = 0; i < iotable.size(); i++) {
IOTableNode node = (IOTableNode) iotable.get(i);
if (node.getCylinder() > cur_cylinder) {
reslist.add(node);
}
}
} else if (mark == 0) {
for (int i = 0; i < iotable.size(); i++) {
IOTableNode node = (IOTableNode) iotable.get(i);
if (node.getCylinder() < cur_cylinder) {
reslist.add(node);
}
}
}
return reslist;
}
/**
* 从大于或者小于的请求中选择最小或者最大的请求
*
* @param mark 1表示方向向里
* @param reslist 大于或小于当前柱面的请求列表
* @return
*/
public IOTableNode selectCylinder(int mark, LinkedList<IOTableNode> reslist) {
int index = 0;
if (mark == 1) {// 在大于当前柱面的请求列表中选择最小的
int min = Integer.MAX_VALUE;
for (int i = 0; i < reslist.size(); i++) {
IOTableNode node = (IOTableNode) reslist.get(i);
if (node.getCylinder() < min) {
min = node.getCylinder();
index = i;
}
}
} else if (mark == 0) {// 在小于当前柱面的请求列表中选择最大的
int max = Integer.MIN_VALUE;
for (int i = 0; i < reslist.size(); i++) {
IOTableNode node = (IOTableNode) reslist.get(i);
if (node.getCylinder() > max) {
max = node.getCylinder();
index = i;
}
}
}
return reslist.get(index);
}
public void printIOTable() {
System.out.println("进程名 柱面号 磁道号 物理记录号");
for (Iterator iterator = iotable.iterator(); iterator.hasNext(); ) {
IOTableNode node = (IOTableNode) iterator.next();
System.out.println(node.getP_name() + " " + node.getCylinder()
+ " " + node.getTrack() + " " + node.getPhy_record());
}
}
public Integer getCur_cylinder() {
return cur_cylinder;
}
public void setCur_cylinder(Integer cur_cylinder) {
this.cur_cylinder = cur_cylinder;
}
public boolean isCur_direction() {
return cur_direction;
}
public void setCur_direction(boolean cur_direction) {
this.cur_direction = cur_direction;
}
public LinkedList<IOTableNode> getIotable() {
return iotable;
}
public void setIotable(LinkedList<IOTableNode> iotable) {
this.iotable = iotable;
}
public Integer getCur_track() {
return cur_track;
}
public void setCur_track(Integer cur_track) {
this.cur_track = cur_track;
}
public Integer getCur_phy_record() {
return cur_phy_record;
}
public void setCur_phy_record(Integer cur_phy_record) {
this.cur_phy_record = cur_phy_record;
}
}