快速实现FCFS算法和SPF算法

先来看看代码的总体结构:

java FC_System

在如上图的流程中,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

希望能帮助到大家^-^