java时间片轮转调度(操作系统课程设计)

操作系统课程设计之时间片轮转调度算法模拟(Java版本可视化)

1. 课程设计要求
本次课程设计的题目是,时间片轮转调度算法的模拟实现。要求在充分理解时间片轮转调度算法原理的基础上,编写一个可视化的算法模拟程序。
具体任务如下:
(1)根据需要,合理设计PCB结构,以适用于时间片轮转调度算法;
(2)设计模拟指令格式,并以文件形式存储,程序能够读取文件并自动生成指令序列。
(3)根据文件内容,建立模拟进程队列,并能采用时间片轮转调度算法对模拟进程进行调度。
任务要求:
(1)进程的个数,进程的内容(即进程的功能序列)来源于一个进程序列描述文件。
(2)需将调度过程输出到一个运行日志文件。
(3)开发平台及语言不限。
(4)要求设计一个Windows可视化应用程序。
2. 课程设计说明
模拟指令的格式:操作命令+操作时间
● C : 表示在CPU上计算
● I : 表示输入
● O : 表示输出
● W : 表示等待
● H : 表示进程结束
操作时间代表该操作命令要执行多长时间(时间片个数)。这里假设I/O设备的数量没有限制,I和O设备都只有一类。
I,O,W三条指令实际上是不占有CPU的,执行这三条指令就应该将进程放入对应的等待队列(输入等待队列,输出等待队列 ,其他等待队列)。

进程名称进程信息
P1C10 I20 C40 I30 C20 O30 H00
P2I10 C50 O20 H00
P3C10 I20 W20 C40 O10 H00

以上表格内容为进程具体时间片安排信息,存放在prc.txt文件中等待读取。

3. 课程设计UI界面
UI界面展示
此处时间片默认为(500)单位为ms
需求分析:
本小程序需要实现的功能以下可见
打开文件 选择文件 读取文件 时间片设置 开始调度 暂停调度 以及最后的日志输出
4. 预备知识
(1)编程需要掌握:
Java基本语法;
此处我用软件eclipse进行Java编程;
Java的swing使用插件 WindowsBulider插件进行UI界面的设计;
Java列表的使用;
Java线程的分配;
插件的安装教程见插件安装教程
(2)时间片轮转调度算法掌握:
(借鉴别人的博客,后面附有连接)
在轮转RR法中,系统根据FCFS策略,将所有的就绪进程排成一个就绪队列,并可设置每隔一定时间间隔(如30 ms)即产生一次中断, 激活系统中的进程调度程序, 完成一次调度,将CPU分配给队首进程,令其执行。当该进程的时间片耗尽或运行完毕时,系统再次将CPU分配给新的队首进程(或新到达的紧迫进程)。由此,可保证就绪队列中的所有进程在一个确定的时间段内,都能够获得次 CPU执行。
5. 关键代码
所有程序包括三个类(个人设计三个,随自己,也可以一个)
PCB类(存放文件读取来的进程的信息)

public class PCB {
    private String pName;//进程名称
    private List pInstructions = new ArrayList<Instructions>();//进程中的指令列表
    private int CurrentInstruction;        //当前运行指令索引
    //后面自己添加其成员的get set方法
    }

Instructions类(动态的获取进程的信息机更新进程信息)

	private char IName;           //指令类型
    private double IRuntime;   //指令运行时间
    private double IRemainTime;  //指令剩余运行时间
    //后面自己添加get set 方法
    //再添加一个时间片控制方法 减时间片
    
     public void subIRemainTime(){
        this.setIRemainTime(this.getIRemainTime()-1);
    }

主类(关键部分,完成整个程序功能的实现,以及界面的展示)

//界面元素的定义
	private JButton bFIle, bStart, bStop;
    private JTextField tTime, tCur;
    private JTextArea tAll, tReady, tInput, tOutput, tWait;//队列文本域
    private File file;
//进程信息列表定义
	private ArrayList<PCB> allQue = new ArrayList<PCB>();
    private ArrayList<PCB> readyQue = new ArrayList<PCB>();
    private ArrayList<PCB> inQue = new ArrayList<PCB>();
    private ArrayList<PCB> outQue = new ArrayList<PCB>();
    private ArrayList<PCB> waitQue = new ArrayList<PCB>();
    private volatile Thread blinker;//Thread线程控制方法
	private long count = 0;//计数器

在主类中定义其他关键方法

文件的读写方法

private void readFile() {
        if (file != null) {
            try {
                BufferedReader in = new BufferedReader(new FileReader(file));
                String str;
                allQue.clear();
                PCB pcb = null;
                while ((str = in.readLine()) != null) {
                    if (str.charAt(0) == 'P') {
                        pcb = new PCB();
                        pcb.setpName(str);
                    } else {
                        Instructions instructions = new Instructions();
                        instructions.setIName(str.charAt(0));
                        instructions.setIRuntime(parseDouble(str.substring(1)));
                        instructions.setIRemainTime(instructions.getIRuntime());
                        assert pcb != null;
                        pcb.getpInstructions().add(instructions);
                        if (instructions.getIName() == 'H') {
                            //H代表当前进程结束,添加到就绪队列
                            allQue.add(pcb);
                        }
                    }
                }
            } catch (IOException e) {
                System.out.println("文件读取错误!");
            }
        }
    }
    private void chooseFile() {
        //选择文件
        FileNameExtensionFilter filter = new 		FileNameExtensionFilter("*.txt", "txt");
        JFileChooser jfc = new JFileChooser(".");//当前目录下
        jfc.setFileFilter(filter);
        jfc.setMultiSelectionEnabled(false);
        jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        int result = jfc.showSaveDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            file = jfc.getSelectedFile();
        }
    }

界面按钮事件

bFIle.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                chooseFile();
                readFile();
                saveLog("读取文件成功!\r\n________________________\r\n");
                showAll(allQue);
            }
        });
        //开始按钮事件
bStart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (allQue.size()==0) {
                    JOptionPane.showMessageDialog(null, "请重新选择文件!",JOptionPane.INFORMATION_MESSAGE);
                    return;
                }
                if (boolTTime()) {
                    initQue();
                    startRun();
                }
            }
        });
bStop.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                bStart.setText("继续调度");
                blinker = null;
            }
        });

初始化队列

private void initQue() {
        readyQue.clear();
        inQue.clear();
        outQue.clear();
        waitQue.clear();
        //分配排序队列
        for (PCB p : allQue) {
            if (p.getpInstructions().get(0).getIName() == 'C') {
                readyQue.add(p);
            } 
            else if (p.getpInstructions().get(0).getIName() == 'I') {
                inQue.add(p);
            }
            else if (p.getpInstructions().get(0).getIName() == 'O') {
                outQue.add(p);
            } 
            else if (p.getpInstructions().get(0).getIName() == 'W') {
                waitQue.add(p);
            }
        }
    }

进程队列运转更新方法

private void runReady() {
        if (readyQue.size() > 0) {
            readyQue.get(0).getpInstructions().get(0).subIRemainTime();//调度首队列一次
            tCur.setText(readyQue.get(0).getpName());
            if (readyQue.get(0).getpInstructions().get(0).getIRemainTime() == 0) {
                readyQue.get(0).getpInstructions().remove(0);
                if (readyQue.get(0).getpInstructions().get(0).getIName() == 'C') {
                    readyQue.add(readyQue.get(0));//添加到ready末尾
                } else if (readyQue.get(0).getpInstructions().get(0).getIName() == 'I') {
                    inQue.add(readyQue.get(0));//添加到in末尾
                } else if (readyQue.get(0).getpInstructions().get(0).getIName() == 'O') {
                    outQue.add(readyQue.get(0));//添加到out末尾
                } else if (readyQue.get(0).getpInstructions().get(0).getIName() == 'W') {
                    waitQue.add(readyQue.get(0));//添加到wait末尾
                } else if (readyQue.get(0).getpInstructions().get(0).getIName() == 'H') {
                    allQue.remove(readyQue.get(0));
                }
                readyQue.remove(readyQue.get(0));
            } else {
                readyQue.add(readyQue.get(0));//移动到末尾
                readyQue.remove(readyQue.get(0));
            }
        }
    }
     private void runIn() {
        if (inQue.size() > 0) {
            inQue.get(0).getpInstructions().get(0).subIRemainTime();//调度首队列一次
            if (inQue.get(0).getpInstructions().get(0).getIRemainTime() == 0) {
                inQue.get(0).getpInstructions().remove(0);
                if (inQue.get(0).getpInstructions().get(0).getIName() == 'C') {
                    readyQue.add(inQue.get(0));//添加到ready末尾
                } else if (inQue.get(0).getpInstructions().get(0).getIName() == 'I') {
                    inQue.add(inQue.get(0));//添加到in末尾
                } else if (inQue.get(0).getpInstructions().get(0).getIName() == 'O') {
                    outQue.add(inQue.get(0));//添加到out末尾
                } else if (inQue.get(0).getpInstructions().get(0).getIName() == 'W') {
                    waitQue.add(inQue.get(0));//添加到wait末尾
                } else if (inQue.get(0).getpInstructions().get(0).getIName() == 'H') {
                    //说明该进程完成
                    allQue.remove(inQue.get(0));
                }
                inQue.remove(inQue.get(0));
            } else {
                inQue.add(inQue.get(0));//移动到末尾
                inQue.remove(inQue.get(0));
            }
        }
    }
    private void runOut() {
        if (outQue.size() > 0) {
            outQue.get(0).getpInstructions().get(0).subIRemainTime();//调度首队列一次
            if (outQue.get(0).getpInstructions().get(0).getIRemainTime() == 0) {
                outQue.get(0).getpInstructions().remove(0);
                if (outQue.get(0).getpInstructions().get(0).getIName() == 'C') {
                    readyQue.add(outQue.get(0));//添加到ready末尾
                } else if (outQue.get(0).getpInstructions().get(0).getIName() == 'I') {
                    inQue.add(outQue.get(0));//添加到in末尾
                } else if (outQue.get(0).getpInstructions().get(0).getIName() == 'O') {
                    outQue.add(outQue.get(0));//添加到out末尾
                } else if (outQue.get(0).getpInstructions().get(0).getIName() == 'W') {
                    waitQue.add(outQue.get(0));//添加到wait末尾
                } else if (outQue.get(0).getpInstructions().get(0).getIName() == 'H') {
                      if (allQue.size() > 0) {
                        allQue.remove(outQue.get(0));
                    }
                }
                outQue.remove(outQue.get(0));
            } else {
                outQue.add(outQue.get(0));//移动到末尾
                outQue.remove(outQue.get(0));
            }
        }
    }
    private void runWait() {
        if (waitQue.size() > 0) {
            waitQue.get(0).getpInstructions().get(0).subIRemainTime();//调度首队列一次
            if (waitQue.get(0).getpInstructions().get(0).getIRemainTime() == 0) {
                waitQue.get(0).getpInstructions().remove(0);
                if (waitQue.get(0).getpInstructions().get(0).getIName() == 'C') {
                    readyQue.add(waitQue.get(0));//添加到ready末尾
                } else if (waitQue.get(0).getpInstructions().get(0).getIName() == 'I') {
                    inQue.add(waitQue.get(0));//添加到in末尾
                } else if (waitQue.get(0).getpInstructions().get(0).getIName() == 'O') {
                    outQue.add(waitQue.get(0));//添加到out末尾
                } else if (waitQue.get(0).getpInstructions().get(0).getIName() == 'W') {
                    waitQue.add(waitQue.get(0));//添加到wait末尾
                } else if (waitQue.get(0).getpInstructions().get(0).getIName() == 'H') {
                    //说明该进程完成
                    allQue.remove(waitQue.get(0));
                }
                waitQue.remove(waitQue.get(0));
            } else {
                waitQue.add(waitQue.get(0));//移动到末尾
                waitQue.remove(waitQue.get(0));
            }
        }

日志的生成方法(日志的生成在程序目录下当然也可以自己随意该位置的)

public void startRun() {
        Runnable runnable = new Runnable() {
            public void run() {
                saveLog("------正在进行调度-------");
                while (allQue.size() > 0 && blinker != null) {
                    try {
                        runReady();
                        runIn();
                        runOut();
                        runWait();
                        showAll(allQue);
                        saveLog("就绪队列:\t" + tAll.getText() + "\r\n");
                        showReady(readyQue);
                        saveLog("后备就绪队列:\t" + tReady.getText() + "\r\n");
                        showIn(inQue);
                        saveLog("输入队列:\t" + tInput.getText() + "\r\n");
                        showOut(outQue);
                        saveLog("输出队列:\t" + tOutput.getText() + "\r\n");
                        showWait(waitQue);
                        saveLog("等待队列:\t" + tWait.getText() + "\r\n");

                        saveLog("_______________________________");
                        count++;
                        System.out.println(count);
                        sleep(Long.parseLong(tTime.getText()));

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (allQue.size() == 0) {
                    bStart.setText("开始调度");
                    tCur.setText("");
                   
                    saveLog("调度已完成");
                } else {
                    
                    saveLog("调度已停止");
                }
            }
        };
        blinker = new Thread(runnable);
        blinker.start();
    }

其他子方法

 private void showAll(ArrayList<PCB> allQue) {
        tAll.setText("");
        for (PCB p : allQue) {
            tAll.setText(tAll.getText() + "\r\n" + p.getpName());
        }
    }

    private void showWait(ArrayList<PCB> waitQue) {
        tWait.setText("");
        for (PCB p : waitQue) {
            tWait.setText(tWait.getText() + "\r\n" + p.getpName());
        }
    }

    private void showOut(ArrayList<PCB> outQue) {
        tOutput.setText("");
        for (PCB p : outQue) {
            tOutput.setText(tOutput.getText() + "\r\n" + p.getpName());
        }
    }

    private void showIn(ArrayList<PCB> inQue) {
        tInput.setText("");
        for (PCB p : inQue) {
            tInput.setText(tInput.getText() + "\r\n" + p.getpName());
        }
    }

    private void showReady(ArrayList<PCB> que) {
        tReady.setText("");
        for (PCB p : que) {
            tReady.setText(tReady.getText() + "\r\n" + p.getpName());
        }
    }

最后在main方法中新建一个主类,即可运行得到程序。(结构如下)
6. 结果演示
调度中
日志文件

  1. 提供帮助
    本程序的出处来自[此篇博客]感谢这个博主,真的很热心,但在其基础上进一步加以详细描述(适用于我一样的小白),应为当初我看到这篇博客的时候认为看到了救星,结过并不是想的那么详细。如果有一点java基础的同学,想必看到这篇文章后一定对你有所帮助,若没有基础,第一次碰java就别想了吧,就算拿到代码你也不一定跑的出来。
    附java环境配置可以在CSDN上面找到相关教程(关键 JDK的配置,一定要加到环境变量中,eclipse程序方可打开)。
    记住,每个人都不是一座孤岛,遇到困难先别放弃,先在网上找找,因为程序员最好的帮手,就应该有现如今发达的网络。
  • 18
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值