时间轮转法的JAVA实现

  • 操作系统作业需要,续写一段C语言版的时间轮转法的进程调度模拟,我表示我不想、我不要、我不会。
  • 所以我就重构了Java版的(但愿最终给过)
代码说明
  • StreamUtils是工具类,用于序列化IO操作
  • ProcStruct是进程类,这里大多是复制作业要求中的字段定义
  • ProcessScheduling是运行类,包括主函数,各种方法,全局定义等
  • 至于具体内容,个人认为注释写的还算比较详细~
  • 如何运行?运行主函数即可。
package processScheduling;

import java.io.*;
import java.util.Arrays;
import java.util.List;

/**
 * Created by CHEN on 2019/11/6.
 */

public class StreamUtils implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 序列化,List
     *
     * @param list
     * @param file
     * @param <T>
     * @return
     */
    public static <T> boolean writeObject(List<T> list, File file) {
        T[] array = (T[]) list.toArray( );
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file))) {
            out.writeObject(array);
            out.flush( );
            return true;
        } catch (IOException e) {
            e.printStackTrace( );
            return false;
        }
    }

    /**
     * 反序列化,List
     *
     * @param file
     * @param <E>
     * @return
     */
    public static <E> List<E> readObjectForList(File file) {
        E[] object;
        try (ObjectInputStream out = new ObjectInputStream(new FileInputStream(file))) {
            object = (E[]) out.readObject( );
            return Arrays.asList(object);
        } catch (IOException e) {
            e.printStackTrace( );
        } catch (ClassNotFoundException e) {
            e.printStackTrace( );
        }
        return null;
    }

}
package processScheduling;
import java.io.Serializable;
import java.util.Arrays;

/**
 * 进程结构
 * Created by CHEN on 2019/11/5.
 */
public class ProcStruct implements Serializable,Comparable {
    private Integer  p_pid;         // 进程的标识号
    private char p_state;       // 进程的状态,C--运行  R--就绪  W--组塞  B--后备  F--完成
    private Integer[]   p_rserial = new Integer[5]; // 模拟的进程执行的CPU和I/O时间数据序列,间隔存储,第0项存储随后序列的长度(项数),以便知晓啥时该进程执行结束
    private Integer  p_pos;   // 当前进程运行到的位置,用来记忆执行到序列中的哪项
    private Integer  p_starttime;   // 进程建立时间
    private Integer  p_endtime;     // 进程运行结束时间
    private Integer  p_cputime;     // 当前运行时间段进程剩余的需要运行时间
    private Integer  p_iotime;      // 当前I/O时间段进程剩余的I/O时间



//初始化必须给值的量有:p_pid、p_state、p_rserial[]、p_pos=1、p_cputime()、p_endtime、

    public ProcStruct(Integer p_pid,Integer[] p_rserial, Integer p_starttime){
        this.p_pid = p_pid;
        this.p_state = 'B';
        this.p_rserial = p_rserial;
        this.p_pos = 1;//开始是第一项未执行
        this.p_cputime = p_rserial[1];//时间片统一给
        this.p_starttime = p_starttime;//创建时间
    }

    public ProcStruct() {
    }

    public ProcStruct(Integer p_pid, char p_state, Integer[] p_rserial, Integer p_pos, Integer p_starttime, Integer p_endtime, Integer p_cputime, Integer p_iotime) {
        this.p_pid = p_pid;
        this.p_state = p_state;
        this.p_rserial = p_rserial;
        this.p_pos = p_pos;
        this.p_starttime = p_starttime;
        this.p_endtime = p_endtime;
        this.p_cputime = p_cputime;
        this.p_iotime = p_iotime;
    }

    public Integer getP_pid() {
        return p_pid;
    }

    public void setP_pid(Integer p_pid) {
        this.p_pid = p_pid;
    }

    public char getP_state() {
        return p_state;
    }

    public void setP_state(char p_state) {
        this.p_state = p_state;
    }

    public Integer[] getP_rserial() {
        return p_rserial;
    }

    public void setP_rserial(Integer[] p_rserial) {
        this.p_rserial = p_rserial;
    }

    public Integer getP_pos() {
        return p_pos;
    }

    public void setP_pos(Integer p_pos) {
        this.p_pos = p_pos;
    }

    public Integer getP_starttime() {
        return p_starttime;
    }

    public void setP_starttime(Integer p_starttime) {
        this.p_starttime = p_starttime;
    }

    public Integer getP_endtime() {
        return p_endtime;
    }

    public void setP_endtime(Integer p_endtime) {
        this.p_endtime = p_endtime;
    }

    public Integer getP_cputime() {
        return p_cputime;
    }

    public void setP_cputime(Integer p_cputime) {
        this.p_cputime = p_cputime;
    }

    public Integer getP_iotime() {
        return p_iotime;
    }

    public void setP_iotime(Integer p_iotime) {
        this.p_iotime = p_iotime;
    }
    @Override
    public String toString() {
        return "ProcStruct{" +
                "p_pid=" + p_pid +
                ", p_state=" + p_state +
                ", p_rserial=" + Arrays.toString(p_rserial) +
                ", p_pos=" + p_pos +
                ", p_starttime=" + p_starttime +
                ", p_endtime=" + p_endtime +
                ", p_cputime=" + p_cputime +
                ", p_iotime=" + p_iotime +
                '}';
    }
    // 用于list.sort
    @Override
    public int compareTo(Object o) {
        if (o instanceof ProcStruct) {
            ProcStruct procStruct = (ProcStruct) o;
            //首先用starttime比较
            int i = this.p_starttime.compareTo(procStruct.p_starttime);
            if (i == 0) {
                //当前io剩余时间为第二比较标准
                return this.p_iotime.compareTo(procStruct.p_iotime);
            }else {
                return i;
            }
        }
        return 0;
    }
}

package processScheduling;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;

/**
 * Created by CHEN on 2019/11/5.
 */
public class ProcessScheduling {

    public static int ClockNumber;   // 系统时钟
    public static int ProcNumber;    // 系统中模拟产生的进程总数
    public static int FinishedProc;    // 系统中目前已执行完毕的进程总数

    public static ArrayList<ProcStruct> procStructs = new ArrayList<>( );//进程列表

    public static LinkedList<ProcStruct> IOProc = new LinkedList<>( );//CPU运行、阻塞的进程
    public static LinkedList<ProcStruct> CPUProc = new LinkedList<>( );//IO运行、阻塞的进程
    public static LinkedList<ProcStruct> FinProc = new LinkedList<>( );//完成的进程


    // 随机创建进程
    public static void Create_ProcInfo() {
        System.out.println("Create_ProcInfo.......");

        Random random = new Random( );
        Integer[] p_rserial;
        ProcStruct procStruct;
        // 创建至多10个进程
        for (int i = ProcNumber; i < 10; i++) {
            p_rserial = new Integer[4];
            //产生随机数组
            // [1-10)
            p_rserial[0] = random.nextInt(3) + 1;
            for (int j = 1; j <= p_rserial[0]; j++) {
                // [1-5)
                p_rserial[j] = random.nextInt(3) + 1;
            }
            // public ProcStruct(int p_pid,int[] p_rserial, int p_cputime)
            //进程id:1-65535  p_rserial随机生成1-9秒的任务列表 starttime:1-10秒之间
            procStruct = new ProcStruct(random.nextInt(65535)+1, p_rserial, random.nextInt(5) + 1);
            procStructs.add(procStruct);
        }
        //更新ProcNumber
        ProcNumber = procStructs.size( );
        //显示
        DisData( );
    }

    // 展示所创建的进程序列
    public static void DisData() {
        for (ProcStruct proc : procStructs
                ) {
            System.out.println(proc);
        }
        //序列化保存
        StreamUtils.writeObject(procStructs, new File("./prStructs.txt"));
    }


    // 进程调度函数
    public static void Scheduler_FF() {

        if (ProcNumber == 0) {
            procStructs = new ArrayList<>( );
            // 如果队列中没有进程则向文件中读取上次保存的进程
            for (Object p : StreamUtils.readObjectForList(new File("./prStructs.txt"))
                    ) {
                procStructs.add((ProcStruct) p);
            }
            ProcNumber = procStructs.size( );
        }
//        //验证是否拿到
//        for (ProcStruct p: procStructs
//                ) {
//            System.out.println(p );
//        }
        FinProc = new LinkedList<>( );
        FinishedProc = 0;
        //时钟初始化
        ClockNumber = 0;
        // 执行算法
        while (FinishedProc < ProcNumber) {
            ClockNumber++;  // 时钟前进1个单位
            NewReadyProc( ); // 判别新进程是否到达
            Cpu_Sched( );    // CPU调度
            IO_Sched( );     // IO调度
            Display_ProcInfo( ); //显示当前状态

            // 睡眠0.7s
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace( );
            }
        }
        Cal();
        //清空当前队列,要上次的内容去.class文件中找出数据重新运行一遍
        procStructs.clear( );
        ProcNumber = 0;

    }

    // 判断当前是否有新进程到达
    public static void NewReadyProc() {
        for (ProcStruct p : procStructs
                ) {
            if (p.getP_starttime( ) == ClockNumber) {
                // 进程的状态,C--运行  R--就绪  W--组塞  B--后备  F--完成
                if (CPUProc.size( ) == 0) {
                    p.setP_state('R');
                }
                else {
                    p.setP_state('W');
                }
                // 如果有加到CPU队列末尾(默认~CPU先)
                CPUProc.add(p);
            }
        }
    }

    // CPU调度模拟, 每次只执行一个CPU时间片p=1
    public static void Cpu_Sched() {
        if (CPUProc.size( ) != 0) {

            // 弹出一个
            ProcStruct procStruct = CPUProc.pop( );
            //变为运行状态
            State_Change(0, procStruct);
            if (procStruct.getP_state( ) == 'C') {
                procStruct.setP_cputime(procStruct.getP_cputime( ) - 1);
                //如果cup运行时间耗尽
                if (procStruct.getP_cputime( ) == 0) {
                    //且进程进度已经到了最后,进程完成,加入完成队列
                    if (procStruct.getP_pos( ).equals(procStruct.getP_rserial( )[0])) {
                        // 进程结束,进入结束队列(为了好收集)
                        Proc_Finish(procStruct);
                    } else if (procStruct.getP_pos( ) < procStruct.getP_rserial( )[0]) {
                        //进度未到最后,进程进度+1
                        procStruct.setP_pos(procStruct.getP_pos( ) + 1);
                        //IO剩余时间赋值
                        procStruct.setP_iotime(procStruct.getP_rserial( )[procStruct.getP_pos( )]);
                        //加到IO队列尾 12
                        procStruct = State_Change(1, procStruct);
                        IOProc.add(procStruct);
                    }
                } else if (procStruct.getP_cputime( ) > 0) {
                    //放回CPU队尾 11
                    procStruct = State_Change(1, procStruct);
                    CPUProc.add(procStruct);
                }
                Head_State_Change(0);
            } else {
                CPUProc.add(procStruct);
            }
        }
    }


    // I/O调度模拟, 与CPU调度操作类似。排在队首的进程得到一个时间片服务
    public static void IO_Sched() {

        if (IOProc.size( ) != 0) {
            // 弹出一个
            ProcStruct procStruct = IOProc.pop( );

            procStruct = State_Change(0, procStruct);
            if (procStruct.getP_state( ) == 'C') {

                procStruct.setP_iotime(procStruct.getP_iotime( ) - 1);
                //如果cup运行时间耗尽
                if (procStruct.getP_iotime( ) == 0) {
                    //且进程进度已经到了最后,进程完成,加入完成队列
                    if (procStruct.getP_pos( ).equals(procStruct.getP_rserial( )[0])) {
                        Proc_Finish(procStruct);


                    } else if (procStruct.getP_pos( ) < procStruct.getP_rserial( )[0]) {
                        //进度未到最后,进程进度+1
                        procStruct.setP_pos(procStruct.getP_pos( ) + 1);
                        //CPU剩余时间赋值
                        procStruct.setP_cputime(procStruct.getP_rserial( )[procStruct.getP_pos( )]);
                        //加到CPU队列尾 21
                        procStruct = State_Change(1, procStruct);
                        CPUProc.add(procStruct);
                        // 如果CPU队列只有刚转进去的元素,则其状态立马变为R
                        if (CPUProc.size( ) == 1) {
                            Head_State_Change(0);
                        }
                    }


                } else if (procStruct.getP_iotime( ) > 0) {
                    //IO->IO 22
                    procStruct = State_Change(1, procStruct);
                    IOProc.add(procStruct);
                }
                Head_State_Change(1);
            } else {
                IOProc.add(procStruct);
            }

        }
    }

    // 显示系统当前状态,每秒运行完毕之后都显示一次
    public static void Display_ProcInfo() {

        //显示:CPU队列?IO队列?阻塞状态?非阻塞状态?
        System.out.println("\n当第:" + ClockNumber+"秒运行完毕之后");
        System.out.println("CPUProc:");
        for (ProcStruct p : CPUProc
                ) {
            System.out.println(p);
        }
        System.out.println("IOProc:");
        for (ProcStruct p : IOProc
                ) {
            System.out.println(p);
        }
        System.out.println("FinProc:");
        for (ProcStruct p : FinProc
                ) {
            System.out.println(p);
        }
    }


    // 元素的状态转换
    public static ProcStruct State_Change(int type, ProcStruct procStruct) {
        //type: 1=做完一次CPU/IO之后的元素的转换 0=做之前的转换,或者下次头元素的状态转换
        if (type == 1) {
            procStruct.setP_state('W');
        } else if (type == 0) {
            if (procStruct.getP_state( ) == 'W') {
                procStruct.setP_state('R');
            } else if (procStruct.getP_state( ) == 'R') {
                procStruct.setP_state('C');
            }

        }
        return procStruct;
    }

    // CPU与IO:队列的第一个进程的状态转换
    public static void Head_State_Change(int type) {
        //type: 0=CPU队列头部元素状态的转换,1代表的是IO队列头部元素状态的转换
        if (type == 0) {
            if (CPUProc.size( ) >= 1) {
                //这段是把下一个进程标记为R
                ProcStruct procStruct = CPUProc.pop( );
                State_Change(0, procStruct);
                CPUProc.addFirst(procStruct);
            }
        } else if (type == 1) {
            if (IOProc.size( ) >= 1) {
                //这段是把下一个进程标记为R
                ProcStruct procStruct = IOProc.pop( );
                State_Change(0, procStruct);
                IOProc.addFirst(procStruct);
            }
        }
    }

    // 将运行完毕的进程加入结束队列,以便于显示,非系统调度内容
    public static void Proc_Finish(ProcStruct procStruct) {
        procStruct.setP_state('F');
        procStruct.setP_endtime(ClockNumber);
        FinProc.add(procStruct);
        FinishedProc = FinProc.size( );
    }
    // 计算周转时间,带权周转时间
    public static  void  Cal(){
        System.out.println("\n周转/带权周转时间为:");
        for (ProcStruct p:FinProc
             ) {
            int total_time=p.getP_endtime()-p.getP_starttime();
            int service_time =0;
            for (int i=1;i<=p.getP_rserial()[0];i++){
                service_time+=p.getP_rserial()[i];
            }
            System.out.println("ID:"+p.getP_pid()+"\t周转时间:"+total_time+"\t带权周转时间:"+(total_time*1.0/service_time));
        }
    }

    public static void main(String[] args) {
        //初始化
        char ch;
        ClockNumber = 0;   // 系统时钟
        ProcNumber = 0;    // 当前系统中的进程总数
        FinishedProc = 0;

        while (true) {
            System.out.println("***********************************");
            System.out.println("     1: 建立进程调度数据序列 ");
            System.out.println("     2: 读进程信息,执行调度算法");
            System.out.println("     3: 退出");
            System.out.println("***********************************");
            System.out.println("Enter your choice (1 ~ 3): ");
            try {
                ch = (char) System.in.read( ); //如果输入信息不正确,继续输入
                if (ch == '2') Scheduler_FF( );     // 选择2
                else if (ch == '1') Create_ProcInfo( );  // 选择1
                else if (ch == '3') System.exit(0);  // 选择3
                else System.out.println("Error input......");//错误输入
                ch = (char) System.in.read( );
            } catch (Exception e) {
                e.printStackTrace( );
            }
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椰子奶糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值