操作系统课程设计——进程调度模拟程序(JAVA语言实现)

本科期间的一些学习回忆记录(自己用)


一、课程设计的任务和要求

       本次课程设计的题目是,时间片轮转调度算法的模拟实现。要求在充分理解时间片轮转调度算法原理的基础上,编写一个可视化的算法模拟程序。
 具体任务如下:

  1. 根据需要,合理设计PCB结构,以适用于时间片轮转调度算法;
  2. 设计模拟指令格式,并以文件形式存储,程序能够读取文件并自动生成指令序列。
  3. 根据文件内容,建立模拟进程队列,并能采用时间片轮转调度算法对模拟进程进行调度。

 任务要求:
4. 进程的个数,进程的内容(即进程的功能序列)来源于一个进程序列描述文件。
5. 需将调度过程输出到一个运行日志文件。
6. 开发平台及语言不限。
7. 要求设计一个Windows可视化应用程序。

二、模拟程序的描述

模拟指令的格式:操作命令+操作时间
● C : 表示在CPU上计算
● I : 表示输入
● O : 表示输出
● W : 表示等待
● H : 表示进程结束
操作时间代表该操作命令要执行多长时间(时间片个数)。这里假设I/O设备的数量没有限制,I和O设备都只有一类。
I,O,W三条指令实际上是不占有CPU的,执行这三条指令就应该将进程放入对应的等待队列(输入等待队列,输出等待队列 ,其他等待队列)。
例如,有一虚拟程序文件prc.txt描述如下,其中,指令后面的数值代表该指令需要执行的时间片个数,如C10,代表需要计算10个时间片:
P1
C10
I20
C40
I30
C20
O30
H00
P2
I10
C50
O20
H00
P3
C10…

三、进程队列及结构图

图1 PCB结构及队列模型
                                                               图1    PCB结构及队列模型

四、运行结果截图

图2 程序主界面                                                               图2    程序主界面

图3  打开文件
                                                               图3    打开文件

图4  运行过程                                                               图4    运行过程

五、代码结构

图5  代码结构
                                                               图5 代码结构

六、主要代码部分

1.TurnQueue

package Queue;

import java.util.*;

import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import IOFile.WriteLogFile;
import ResourceUnit.Instruction;
import ResourceUnit.PCB;

public class TurnQueue {
	private ReadyQueue rq;
	private IWaitQueue iq = new IWaitQueue(this);//把当前对象作为该队列的调度管理对象
	private OWaitQueue oq = new OWaitQueue(this);
	private WaitQueue wq = new WaitQueue(this);
	
	private long interval;//日志文件需要,记录时间间隔
	
	private JTextField currP;//图形界面的显示
	private JTextArea jrq,jiq,joq,jwq;
	private JButton jsb;//程序运行结束,将暂停调度键设置为不可操作

	private void isEndTurn(){
		if(rq.readyQueue.size() == 0 && iq.iWaitQueue.size() == 0 && oq.oWaitQueue.size() == 0
				&& wq.waitQueue.size() == 0){
			rq.readyQueueTimer.cancel();
			iq.iWaitQueueTimer.cancel();
			oq.oWaitQueueTimer.cancel();
			wq.waitQueueTimer.cancel();
			jsb.setEnabled(false);
		}
	}
	
	private StringBuilder outChanged(LinkedList<PCB> list){
		StringBuilder sb = new StringBuilder();
		Iterator<PCB> iter = list.iterator();
		while(iter.hasNext()){
			PCB p = iter.next();
			Instruction i = p.getList().getFirst();
			sb.append(p.name+":"+i.getiName()+i.getRunTime()+"\t");
		}
		sb.append('\n');
		return sb;
	}
	
	private void outReadyQueue(){
		StringBuilder sb = new StringBuilder();
		if(rq.readyQueue.size() > 0){			
			Iterator<PCB> iter = rq.readyQueue.iterator();
			currP.setText(iter.next().name);
			while(iter.hasNext()){
				sb.append(iter.next().name  + "\n");
			}
		}else{
			currP.setText("当前CPU没有指令运行");
			jrq.setText("");
		}
		jrq.setText(sb.toString());
	}
	
	
	private void outWaitQueue(JTextArea jta,LinkedList<PCB> list){
		StringBuilder sb = new StringBuilder();
		Iterator<PCB> iter = list.iterator();
		while(iter.hasNext()){
			sb.append(iter.next().name + "\n");
		}
		jta.setText(sb.toString());
	}
	
	
	public TurnQueue(LinkedList<PCB> list,int turnTime,JButton jsb,
			JTextField currP,JTextArea jrq, JTextArea jiq, JTextArea joq, JTextArea jwq){
		rq = new ReadyQueue(list, turnTime, this);
		this.jsb = jsb;
		this.currP = currP;
		this.jrq = jrq;
		this.jiq = jiq;
		this.joq = joq;
		this.jwq = jwq;
		
		/*启动调度
		 * 遍历后备就绪队列,将每个PCB的第一条指令为非C指令的PCB挂到对应等待队列上
		 * 并为对应等待队列设置定时器
		 * */
		for(int i = 0; i < rq.readyQueue.size(); i++){
			char iName = QueueUtil.getFirst(rq.readyQueue, i).getiName();
			if(iName == 'C'){
				continue;
			}

			if(iName == 'I'){
				iq.iWaitQueue.add(list.remove(i));
			}else if(iName == 'O'){
				oq.oWaitQueue.add(list.remove(i));
			}else if(iName == 'W'){
				wq.waitQueue.add(list.remove(i));
			}else{//要么为H指令,要么指令出错,两种情况都有问题,都要删掉该PCB
				rq.readyQueue.remove(i);
			}
		}

		if(iq.iWaitQueue.size() != 0){
			iq.setTimer();
		}
		if(oq.oWaitQueue.size() != 0){
			oq.setTime();
		}
		if(wq.waitQueue.size() != 0){
			wq.setTime();
		}
		if (rq.readyQueue.size() != 0){			
			rq.setTimer();
		}
		//输出所有队列
		interval = System.currentTimeMillis();
		WriteLogFile.writeLogFile("当前时间点:原点0\n");
		WriteLogFile.writeLogFile("\t就绪队列:" + outChanged(rq.readyQueue));
		WriteLogFile.writeLogFile("\t输入等待队列:" + outChanged(iq.iWaitQueue));
		WriteLogFile.writeLogFile("\t输出等待队列:" + outChanged(oq.oWaitQueue));
		WriteLogFile.writeLogFile("\t其他等待队列:" + outChanged(wq.waitQueue));
		outReadyQueue();
		outWaitQueue(jiq, iq.iWaitQueue);
		outWaitQueue(joq, oq.oWaitQueue);
		outWaitQueue(jwq, wq.waitQueue);
	}

	public void rAtomOperation(){
		WriteLogFile.writeLogFile("当前时间点:" + (System.currentTimeMillis() - interval)/1000 + "\n");
		rq.reduceFirstITime();
		if(0 == QueueUtil.getFirst(rq.readyQueue, 0).getRunTime()){//当前指令执行结束
			rq.readyQueue.getFirst().getList().removeFirst();//删除这条指令
			//根据后面的指令判断接下来的操作
			char iName = QueueUtil.getFirst(rq.readyQueue, 0).getiName();
			switch (iName) {
			case 'I':
				/*若后一条指令为I指令,则将输入等待队列定时器任务取消,然后将等待队列上的I指令的运行时间减去
				*已运行的时间,挂上新指令,并重新定时。
				*执行到上一句时,iTask任务已做和未做都没问题。
				*由于I队列是进程同步的,如果此时iTask在另一个线程正在执行
				*此时下面的代码将会等待iTask处理结束后,本进程才能获得I队列
				*/
				iq.inQueue(rq.readyQueue, 0);
				WriteLogFile.writeLogFile("\t输入等待队列:" + outChanged(iq.iWaitQueue));
				outWaitQueue(jiq, iq.iWaitQueue);
				break;
			case 'O':
				oq.inQueue(rq.readyQueue, 0);
				WriteLogFile.writeLogFile("\t输出等待队列:" + outChanged(oq.oWaitQueue));
				outWaitQueue(joq, oq.oWaitQueue);
				break;
			case 'W':
				wq.inQueue(rq.readyQueue, 0);
				WriteLogFile.writeLogFile("\t其他等待队列:" + outChanged(wq.waitQueue));
				outWaitQueue(jwq, wq.waitQueue);
				break;
			case 'H':
				rq.readyQueue.remove(0);
				break;
			}
		}else{//当前指令未执行结束
			rq.readyQueue.add(rq.readyQueue.remove(0));//直接将队首PCB挂在队尾
		}
		//重新为就绪队列制定定时任务
		if(rq.readyQueue.size() != 0){					
			rq.setTimer();
		}else{//判断是否所有队列为空,是则结束所有Timer
			isEndTurn();
		}
		WriteLogFile.writeLogFile("\t就绪队列:" + outChanged(rq.readyQueue));
		outReadyQueue();
	}

	public void iAtomOperation(){
		/*遍历当前队列,把每个PCB的队首指令运行时间减去已运行时间,若指令运行时间变为零,删除该指令
		 *并根据下一条指令把该PCB挂到对应队列(若下条指令为H,则删除此PCB)
		 *若新队列为就绪队列,则简单的将其挂到队尾即可
		 *若新队列非就绪队列且非空,则将新队列上所有PCB的队首指令减去已运行的时间,然后重新该队列定时
		 */
		WriteLogFile.writeLogFile("当前时间点:" + (System.currentTimeMillis() - interval)/1000 + "\n");
		for(int i = 0; i < iq.iWaitQueue.size(); i++){
			iq.reduceiITime(i);
			if(0 == QueueUtil.getFirst(iq.iWaitQueue, i).getRunTime()){
				//运行时间为0,该指令运行结束,删除该指令
				iq.iWaitQueue.get(i).getList().removeFirst();
				char iName = QueueUtil.getFirst(iq.iWaitQueue, i).getiName();
				switch (iName) {
				case 'C':
					rq.readyQueue.add(iq.iWaitQueue.remove(i));
					if(rq.readyQueue.size() == 1){//表明再添加之前就绪队列已经为空,此时已经没有定时任务了
						rq.setTimer();
					}
					WriteLogFile.writeLogFile("\t就绪队列:" + outChanged(rq.readyQueue));
					outReadyQueue();
					break;
				case 'O':
					//下一步要向输出等待进程添加进程,要重新制定定时任务
					oq.inQueue(iq.iWaitQueue, i);
					WriteLogFile.writeLogFile("\t输出等待队列:" + outChanged(oq.oWaitQueue));
					outWaitQueue(joq, oq.oWaitQueue);
					break;
				case 'W':
					wq.inQueue(iq.iWaitQueue, i);
					WriteLogFile.writeLogFile("\t其他等待队列:" + outChanged(wq.waitQueue));
					outWaitQueue(jwq, wq.waitQueue);
					break;
				case 'H':
					iq.iWaitQueue.remove(i);
					break;
				}
			}

		}
		//最后重新setIWaitQueueTimer
		if(iq.iWaitQueue.size() != 0){			
			iq.setTimer();
		}else{
			isEndTurn();
		}
		WriteLogFile.writeLogFile("\t输入等待队列:" + outChanged(iq.iWaitQueue));
		outWaitQueue(jiq, iq.iWaitQueue);
	}

	public void oAtomOperation(){//同iAtomOperation情况
		WriteLogFile.writeLogFile("当前时间点:" + (System.currentTimeMillis() - interval)/1000 + "\n");
		for(int i = 0; i < oq.oWaitQueue.size(); i++){
			oq.reduceiITime(i);
			if(0 == QueueUtil.getFirst(oq.oWaitQueue, i).getRunTime()){
				//运行时间为0,该指令运行结束,删除该指令
				oq.oWaitQueue.get(i).getList().removeFirst();
				char iName = QueueUtil.getFirst(oq.oWaitQueue, i).getiName();
				switch (iName) {
				case 'C':
					rq.readyQueue.add(oq.oWaitQueue.remove(i));
					if(rq.readyQueue.size() == 1){//表明再添加之前就绪队列已经为空,此时已经没有定时任务了
						rq.setTimer();
					}
					WriteLogFile.writeLogFile("\t就绪队列:" + outChanged(rq.readyQueue));
					outReadyQueue();
					break;
				case 'I':
					iq.inQueue(oq.oWaitQueue, i);
					WriteLogFile.writeLogFile("\t输入等待队列:" + outChanged(iq.iWaitQueue));
					outWaitQueue(jiq, iq.iWaitQueue);
					break;
				case 'W':
					wq.inQueue(oq.oWaitQueue, i);
					WriteLogFile.writeLogFile("\t其他等待队列:" + outChanged(wq.waitQueue));
					outWaitQueue(jwq, wq.waitQueue);
					break;
				case 'H':
					oq.oWaitQueue.remove(i);
					break;
				}
			}

		}
		//最后重新setOWaitQueueTimer
		if(oq.oWaitQueue.size() != 0){			
			oq.setTime();
		}else{
			isEndTurn();
		}
		WriteLogFile.writeLogFile("\t输出等待队列:" + outChanged(oq.oWaitQueue));
		outWaitQueue(joq, oq.oWaitQueue);
	}

	public void wAtomOperation(){//同iAtomOperation情况
		WriteLogFile.writeLogFile("当前时间点:" + (System.currentTimeMillis() - interval)/1000 + "\n");
		for(int i = 0; i < wq.waitQueue.size(); i++){
			wq.reduceiITime(i);
			if(0 == QueueUtil.getFirst(wq.waitQueue, i).getRunTime()){
				//运行时间为0,该指令运行结束,删除该指令
				wq.waitQueue.get(i).getList().removeFirst();
				char iName = QueueUtil.getFirst(wq.waitQueue, i).getiName();
				switch (iName) {
				case 'C':
					rq.readyQueue.add(wq.waitQueue.remove(i));
					if(rq.readyQueue.size() == 1){//表明再添加之前就绪队列已经为空,此时已经没有定时任务了
						rq.setTimer();
					}
					WriteLogFile.writeLogFile("\t就绪队列:" + outChanged(rq.readyQueue));
					outReadyQueue();
					break;
				case 'I':
					iq.inQueue(wq.waitQueue, i);
					WriteLogFile.writeLogFile("\t输入等待队列:" + outChanged(iq.iWaitQueue));
					outWaitQueue(jiq, iq.iWaitQueue);
					break;
				case 'O':
					oq.inQueue(wq.waitQueue, i);
					WriteLogFile.writeLogFile("\t输出等待队列:" + outChanged(oq.oWaitQueue));
					outWaitQueue(joq, oq.oWaitQueue);
					break;
				case 'H':
					wq.waitQueue.remove(i);
					break;
				}
			}

		}
		//最后重新setWaitQueueTimer
		if(wq.waitQueue.size() != 0){			
			wq.setTime();
		}else{
			isEndTurn();
		}
		WriteLogFile.writeLogFile("\t其他等待队列:" + outChanged(wq.waitQueue));
		outWaitQueue(jwq, wq.waitQueue);
	}
	//暂停调度的方法
	public void pauseTurn(){
		rq.pause();
		iq.pause();
		oq.pause();
		wq.pause();
		WriteLogFile.writeLogFile("当前时间点:" + (System.currentTimeMillis() - interval)/1000 + "\n");
		WriteLogFile.writeLogFile("此时调度暂停.......\n\n");
	}
	//重新开始调度的方法
	public void reStartTurn(){
		rq.reStart();
		iq.reStart();
		oq.reStart();
		wq.reStart();
		WriteLogFile.writeLogFile("当前时间点:" + (System.currentTimeMillis() - interval)/1000 + "\n");
		WriteLogFile.writeLogFile("此时调度重新开始。\n\n");
	}
}

2. PCB

package ResourceUnit;

import java.util.LinkedList;

public class PCB {
	public String name;
	private LinkedList<Instruction> list = new LinkedList<Instruction>();
	
	public PCB(){}
	public PCB(String name){
		this.name = name;
	}
	
	public LinkedList<Instruction> getList(){
		return list;
	}
	
	public void addInstruction(Instruction i){
		list.add(i);
	}
	
	public void deleteInstruction(){
		list.removeFirst();
	}

}

七、完整资源

下载链接:
操作系统课程设计—时间片轮转调度算法的进程调度程序实现
包含

  1. 完整的项目代码,运行时出现错误:
    java: 错误: 无效的源发行版:13
    自行检查JDK版本
  2. 课程设计任务书
  3. 课程设计报告
  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

亲爱的老吉先森

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

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

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

打赏作者

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

抵扣说明:

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

余额充值