快速实现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
希望能帮助到大家^-^