快速实现FCFS算法和SPF算法
先来看看代码的总体结构:
在如上图的流程中,FCFS算法和SJF算法唯一的区别就是中间步骤的排序方法不同。因此,只需要替换代码中的排序方法即可。
本程序中,默认是FCFS算法,如果需要SPF算法,可以将dequeue()
方法中被注释的sortJcbsByServeTime()
方法打开即可
代码中的注释相对详细,有因为是早些时候写的,所以某些地方设计的不是特别好,还请理解
代码
- JCB实体类:
package fcfs;
import java.text.DecimalFormat;
public class JCB {
/**
* 作业名
*/
String name;
/**
* 到达时间
*/
int arriveTime;
/**
* 服务时间
*/
int serveTime;
/**
* 开始时间
*/
int beginTime;
/**
* 结束时间
*/
int finishTime;
/**
* 周转时间
*/
int roundTime;
/**
* 带权周转时间
*/
double aveRoundTime;
public JCB() {
}
public JCB(String name, int arriveTime, int serveTime) {
super();
this.name = name;
this.arriveTime = arriveTime;
this.serveTime = serveTime;
}
@Override
public String toString() {
DecimalFormat df = new DecimalFormat("#0.00");
return name + "\t\t"
+ arriveTime + "\t\t"
+ serveTime + "\t\t"
+ beginTime + "\t\t"
+ finishTime + "\t\t"
+ roundTime + "\t\t"
+ df.format(aveRoundTime);
}
}
- ProcessQueue
package fcfs;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
public class ProcessQueue {
//jcbs的下标
int index = 0;
//当前的时间
private int currentTime = 0;
//所有任务
private ArrayList<JCB> jcbs;
//就绪队列
private LinkedList<JCB> ready = new LinkedList();
//执行结束后的结果
private ArrayList<JCB> result = new ArrayList<>();
//平均周转时间
private double avgRoundTime = 0;
//周转时间和
private double sumRoundTime = 0;
//平均带权周转时间
private double avgAveRoundTime = 0;
//带权周转时间和
private double sumAveRoundTime = 0;
public ProcessQueue(ArrayList<JCB> jcbs) {
this.jcbs = jcbs;
//排序(如果是FCFS算法,则不能被注释)
sortJcbs();
}
/**
* 将要做的所有作业按照到达顺序进行排序
*/
public void sortJcbs() {
Collections.sort(jcbs,(o1, o2) -> {
int time = o1.arriveTime - o2.arriveTime;
if (time > 0) {
return 1;
}else if (time == 0) {
//到达时间相同就比较服务时间
return o1.serveTime > o2.serveTime ? 1 : -1;
}else {
return -1;
}
});
}
/**
* 用于SJF算法
* 对已到达的作业作业优先按照服务时间进行排序
*/
public void sortJcbsByServeTime() {
Collections.sort(ready,(o1, o2) -> {
int time = o1.serveTime - o2.serveTime;
if (time > 0) {
return 1;
}else if (time == 0) {
//到达时间相同就比较服务时间
return o1.arriveTime > o2.arriveTime ? 1 : -1;
}else {
return -1;
}
});
}
/**
* 到达的作业进入就绪队列
*/
public void enqueue() {
while (index < jcbs.size()) {
if (jcbs.get(index).arriveTime <= currentTime) {
//出队,index++,避免以及出队的进程重复出队
ready.add(jcbs.get(index));
index++;
}else {
break;
}
}
}
/**
* 第一个执行完的作业出队
*/
public void dequeue() {
if (!ready.isEmpty()) {
//如果是(SJF算法,则下面这个方法不能被注释)
//sortJcbsByServeTime();
JCB jcb = ready.removeFirst();
//设置出队列后的jcb的属性
jcb.beginTime = currentTime;
jcb.finishTime = jcb.beginTime + jcb.serveTime;
jcb.roundTime = jcb.finishTime - jcb.arriveTime;
jcb.aveRoundTime = (double) jcb.roundTime / jcb.serveTime;
//重置当前时间
currentTime = jcb.finishTime;
//记录出队列的结果
result.add(jcb);
}
}
/**
* 打印当前队列状况
*/
public void showReady() {
// for (int i = 1; i < ready.size(); i++) {
// System.out.println("第" + i + "次队列情况:" + ready);
// }
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("当前已到达的进程的情况:");
ready.stream().forEach(r -> {
stringBuilder.append(r.name + " ");
});
System.out.println(stringBuilder.toString());
}
/**
* 执行程序
*/
public void run() {
//当有作业的时候就一直循环
while (index < jcbs.size()) {
//出队一个
dequeue();
//让到达的进程入队
enqueue();
//没有作业到达的时候,就等一下
if (ready.isEmpty()) {
currentTime++;
}
}
dequeue();
dequeue();
dequeue();
System.out.println("++++++++++++++++++++++执++++++++行++++++++结++++++++果++++++++++++++++++");
System.out.println("作业名" + "\t到达时间" + "\t服务时间" + "\t开始时间" + "\t完成时间" + "\t周转时间" + "\t带权周转时间");
result.stream().forEach(s -> {
sumRoundTime += s.roundTime;
sumAveRoundTime += s.aveRoundTime;
System.out.println(s);
});
DecimalFormat df = new DecimalFormat("#0.00");
avgAveRoundTime = sumAveRoundTime/result.size();
avgRoundTime = sumRoundTime/result.size();
System.out.println("平均周转时间:" + df.format(avgRoundTime));
System.out.println("平均带权周转时间 " + df.format(avgAveRoundTime));
}
}
- Main函数:
package fcfs;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
//所有任务
ArrayList<JCB> jcbs = new ArrayList<>();
JCB p1 = new JCB("0", 3, 2);
JCB p2 = new JCB("1", 1, 2);
JCB p3 = new JCB("2", 5, 3);
JCB p4 = new JCB("3", 7, 1);
jcbs.add(p1);
jcbs.add(p2);
jcbs.add(p3);
jcbs.add(p4);
//将任务传入Fcfs程序中运行
ProcessQueue process = new ProcessQueue(jcbs);
process.run();
}
}
运行结果
SPF算法:
++++++++++++++++++++++执++++++++行++++++++结++++++++果++++++++++++++++++
作业名 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间
1 1 2 1 3 2 1.00
0 3 2 3 5 2 1.00
2 5 3 5 8 3 1.00
3 7 1 8 9 2 2.00
平均周转时间:2.25
平均带权周转时间 1.25
FCFS算法:
++++++++++++++++++++++执++++++++行++++++++结++++++++果++++++++++++++++++
作业名 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间
2 1 1 1 2 1 1.00
1 3 4 3 7 4 1.00
3 5 1 7 8 3 3.00
平均周转时间:2.67
平均带权周转时间 1.67
希望能帮助到大家^-^