操作系统--磁头引臂调度SCAN算法 JAVA实现
说明
这次实验课太难受了,一个是对JAVA的synchronize、wait、notify等同步的方法不太熟(自信点,把太去了),不过最终也是完全靠自己把这个功能实现了。还有,本人菜鸡,代码不顺眼,嘴下留人。
重要说明
本博客中的代码能运行且结果正确,但是想法是存在问题的,也有博友私信讨论过了。即本次实现时notifyall唤醒的是随机线程,并不是哪个线程提出的请求,哪个线程就来处理该请求。打个比方:线程A、B分别请求122、100。经过本次程序调用最后有可能是线程A把100请求抱走了,而线程B抱走的是122请求。该处理做法是不对的,违反了线程请求的本意,也就是说结果展示里的Thread-0等根本不是真正的线程!
- 磁头引臂调度算法正确的理解实现见我之后改进的最终版本:https://blog.youkuaiyun.com/guangluo/article/details/108959048
具体要求(看看是不是你需要的做法)
运行结果(如果还有别的输出需求的话可以复制下面代码自己改,注释很详尽)
废话不多说,直接上完整代码(拿去运行)
注意注意,下面这个做了改进,修补了一些问题,还有就是将数组实现换成了ArrayList实现。
package com.guangluo.OS2;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
class Require{
public String name;
public int dest;
public Require(String name, int dest) {
this.name = name;
this.dest = dest;
}
public void setName(String name) {
this.name = name;
}
public void setDest(int dest) {
this.dest = dest;
}
@Override
public String toString() {
return name + " " + dest;
}
}
class Queue{
public ArrayList<Require> queue = null;
public Require r = null;
public Queue(ArrayList<Require> queue) {
this.queue = queue;
}
public void add(Require req) {
queue.add(req);
}
public void del(String name) {
Iterator<Require> iterator = queue.iterator();
while(iterator.hasNext()) {
Require req = iterator.next();
if(req.name == name)
iterator.remove();
}
}
public boolean isNull() {
if(queue == null)
return true;
return false;
}
public void show() {
Iterator<Require> iterator = queue.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next().toString());
}
}
public Require getReq(int orient, int current_dest) {
for(int i = 0; i < queue.size(); i++) {
if(orient == 1) {
if(queue.get(i).dest >= current_dest) {
if(r == null) r = queue.get(i);
r = (r.dest < queue.get(i).dest)? r:queue.get(i);
}
}
if(orient == -1) {
if(queue.get(i).dest <= current_dest) {
if(r == null) r = queue.get(i);
r = (r.dest > queue.get(i).dest)? r:queue.get(i);
}
}
}
if(r == null) {
orient = -1 * orient;
return getReq(orient, current_dest);
}
Require r2 = r;
r = null; // 注意:在把符合规则的第一请求选出来之后,得重新置r为空
System.out.println("当前执行线程 " + r2.name + "提出的请求");
return r2;
}
}
class Scan{
public int current_dest = 100;
public int orient = 1;
public boolean isNull = true; // 表示磁盘是否可访问
public Queue queue = null;
public boolean flag = true; // 表示请求队列是否为空
public Scan(Queue queue) {
this.queue = queue;
}
public void require(int dest) {
System.out.print("当前入队请求:");
System.out.println(Thread.currentThread().getName() + " " + dest);
Require req = new Require(Thread.currentThread().getName(), dest);
if(flag == true) {
ArrayList<Require> q2 = new ArrayList<Require>();
q2.add(req);
queue = new Queue(q2);
flag = false;
}else {
queue.add(req);
}
System.out.println("当前请求队列为:");
queue.show();
}
public synchronized void release() throws InterruptedException{
if(isNull) {
isNull = false;
Thread.sleep(1000);
Require req = queue.getReq(orient, current_dest);
System.out.println("-------------------------------------------");
System.out.print("当前执行的请求为:");
System.out.println("name:" + req.name + "----" + "dest:" + req.dest);
System.out.println("磁道位置变换 :" + current_dest + " --> " + req.dest);
System.out.println("-------------------------------------------");
current_dest = req.dest;
queue.del(req.name);
if(queue.isNull() == true) {
System.out.println("请求队列已经空了");
flag = true;
}
isNull = true;
notifyAll();
}else {
wait();
}
}
}
class MyThread implements Runnable{
public Scan scan;
public MyThread(Scan scan) {
this.scan = scan;
}
@Override
public void run() {
boolean flag = true;
while(flag) {
flag = false;
scan.require(new Random().nextInt(200));
System.out.println("===============================");
try {
Thread.sleep(1000); // 确保该时间段内所有的请求都进入了请求队列
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
scan.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Li {
public static void main(String[] args) {
Queue queue = null;
Scan scan = new Scan(queue); // 共享一个作业调度对象
for(int i = 0; i < 12; i++) {
Thread t = new Thread(new MyThread(scan));
t.start();
try {
Thread.sleep(10); // 每两个请求之间进行略微的延迟
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}