时间片轮转(Round-Robin)调度算法是操作系统一种比较公平的进程调度的方式,这种方式使得就绪队列上的所有进程在每次轮转时都可以运行相同的一个时间片。

基本原理

算法实现原理是,按进程到达顺序(FCFS 原则)将进程依次加入就绪队列当中,然后将 CPU 分配给位于队首的进程,确定一个时间片,让该进程执行一个时间片。当该进程执行时间到时,该进程可能已经执行完毕(可能在时间片未到时就以及执行完毕),或者未执行完毕,如果是前者只需将进程弹出队列即可,如果是后者则将该进程加入队尾,并将 CPU 分配给新的队首进程,如此循环。

进程切换时机

进程在执行时分为两种情况

  • 在该时间片内进程执行完毕,这种情况调度程序将立即把该进程弹出队列,并把 CPU 分配给新的队首进程
  • 在该时间片内进程未执行完毕,调度程序将立即中断该进程执行,把该进程加入队尾,并将 CPU 分配给新的队首进程

时间片大小的确定

在 RR 算法中,时间片的大小直接影响了系统的性能。

  • 时间片过小,有利于短作业,但是会频繁地切换进程,增加了系统的开销,影响性能。
  • 时间片过大,算法退化成 FCFS 算法,如果某个短作业进程之前的进程都是长作业,将导致后面的短作业进程长时间等待。

有关的计算

  • 周转时间 = 进程完成时间 - 进程到达时间
  • 带权周转时间 = 进程周转时间 / 进程实际运行时间
  • 平均周转时间 = (进程1周转时间 + ... + 进程n周转时间)/ n
  • 平均带权周转时间 = (进程1带权周转时间 + ... + 进程n带权周转时间)/ n

实现

package cn.vecrates.operatingSystem;

import java.util.*;
import java.util.concurrent.LinkedBlockingQueue; public class RR {
private int mProcessCount; //进程数
private Queue<Process> mReadyQueue; //就绪队列,存放“待运行的进程
private Queue<Process> mUnreachQueue; //存放“到达时间未到的进程”
private int mTimeSlice; //时间片 private Queue<Process> mExecutedQueue; //执行完毕的进程队列
private double mTotalWholeTime = 0.0;
private double mTotalWeightWholeTime = 0.0; private RR(int processCount, Queue<Process> processQueue, int timeSlice) {
this.mProcessCount = processCount;
this.mUnreachQueue = processQueue;
mReadyQueue = new LinkedBlockingQueue<>();
this.mTimeSlice = timeSlice;
mExecutedQueue = new LinkedList<>();
} /**
* RR 算法实现
*/
public void RRAlgorithm() {
mReadyQueue.add(mUnreachQueue.poll());
Process currProcess = mReadyQueue.poll();
//第一个进程执行
int currTime = executeProcess(currProcess, 0); while(!mReadyQueue.isEmpty() || !mUnreachQueue.isEmpty()) {
//把所有“到达时间”达到的进程加入运行队列头部
while(!mUnreachQueue.isEmpty()) {
if(mUnreachQueue.peek().getArrivalTime() <= currTime) {
mReadyQueue.add(mUnreachQueue.poll());
} else {
break;
}
}java学习群669823128 if(currProcess.getRemainServiceTime() > 0) mReadyQueue.add(currProcess);
//运行队列不为空时
if(!mReadyQueue.isEmpty()) {
currProcess = mReadyQueue.poll();
currTime = executeProcess(currProcess, currTime);
} else {
//当前没有进程执行,但还有进程为到达,时间直接跳转到到达时间
currTime = mUnreachQueue.peek().getArrivalTime();
}
}
} private int executeProcess(Process currProcess, int currTime) {
if(currProcess.getRemainServiceTime() - mTimeSlice <= 0) {
//当前进程在这个时间片内能执行完毕
showExecuteMessage(currTime, currTime += currProcess.getRemainServiceTime(), currProcess.getName());
currProcess.setFinishTime(currTime);
currProcess.setRemainServiceTime(0);
//对周转时间等进行计算
calculeteWholeTime(currProcess);
calculateWeightWholeTime(currProcess);
mTotalWholeTime += currProcess.getWholeTime();
mTotalWeightWholeTime += currProcess.getWeightWholeTime();
mExecutedQueue.add(currProcess);
} else {
//不能执行完毕
showExecuteMessage(currTime, currTime += mTimeSlice, currProcess.getName());
currProcess.setRemainServiceTime(currProcess.getRemainServiceTime() - mTimeSlice);
}
return currTime;
} /**
* 计算周转时间
* @param process
*/
private void calculeteWholeTime(Process process) {
process.setWholeTime(process.getFinishTime() - process.getArrivalTime());
} /**
* 计算带权周转时间
* @param process
*/
private void calculateWeightWholeTime(Process process) {
process.setWeightWholeTime(process.getWholeTime() / (double)process.getServiceTime());
} private void showExecuteMessage(int startTime, int endTime, String name) {
System.out.println(startTime + "~" + endTime + ":【进程" + name + "】运行");
} public void showResult() {
System.out.print("进程名\t");
System.out.print("周转时间\t");
System.out.println("带权周转时间\t");
Process process ;
while(!mExecutedQueue.isEmpty()) {
process = mExecutedQueue.poll();
System.out.print("进程" + process.getName() + "\t");
System.out.print("\t" + process.getWholeTime() + "\t");
System.out.println("\t" + process.getWeightWholeTime() + "\t");
}
System.out.println("平均周转时间:" + mTotalWholeTime / (double) mProcessCount);
System.out.println("平均带权周转时间:" + mTotalWeightWholeTime / (double) mProcessCount);
} public static void printAll(Queue<Process> queue) {
System.out.print("进程名\t");
System.out.print("到达时间\t");
System.out.println("服务时间\t");
Process process = null;
while (!queue.isEmpty()){
process = queue.poll();
System.out.print("进程" + process.getName() + "\t");
System.out.print("\t" + process.getArrivalTime() + "\t");
System.out.println("\t" + process.getServiceTime() + "\t");
}
} public static void main(String[] args) throws InterruptedException {
Scanner scanner = new Scanner(System.in);
System.out.println("输入进程个数:");
int processCount = scanner.nextInt();
if(processCount < 1) return;
Queue<Process> queue = new LinkedBlockingQueue<>();
System.out.println("依次输入每个进程的到达时间(按到达顺序):");
for(int i=0; i<processCount; i++) {
Process process = new Process((char)(i + 65) + "");
process.setArrivalTime(scanner.nextInt());
queue.add(process);
}
System.out.println("依次输入每个进程的服务时间(按到达顺序):");
for(int i=0; i<processCount; i++) {
Process process = queue.poll();
int time = scanner.nextInt();
process.setServiceTime(time);
process.setRemainServiceTime(time);
queue.add(process);
} System.out.println("输入时间片大小");
int timeSlice = scanner.nextInt(); RR rr = new RR(processCount, queue, timeSlice); System.err.println("*******************进程情况*****************");
Thread.sleep(1000);
printAll(new LinkedBlockingQueue<>(queue));
Thread.sleep(1000); System.err.println("******************运行过程*****************");
Thread.sleep(1000);
rr.RRAlgorithm();
Thread.sleep(1000); System.err.println("*******************运行结果*****************");
Thread.sleep(1000);
rr.showResult();
} } //进程
class Process {
private String name;
private int arrivalTime; //到达时间
private int serviceTime; //服务时间
private int remainServiceTime; //还需要服务的时间
private int finishTime; //完成时间
private int wholeTime; //周转时间
private double weightWholeTime; //带权周转时间 public int getRemainServiceTime() {
return remainServiceTime;
} public void setRemainServiceTime(int remainServiceTime) {
this.remainServiceTime = remainServiceTime;
} public Process(String name) {
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getArrivalTime() {
return arrivalTime;
} public void setArrivalTime(int arrivalTime) {
this.arrivalTime = arrivalTime;
} public int getServiceTime() {
return serviceTime;
} public void setServiceTime(int serviceTime) {
this.serviceTime = serviceTime;
} public int getFinishTime() {
return finishTime;
} public void setFinishTime(int finishTime) {
this.finishTime = finishTime;
} public int getWholeTime() {
return wholeTime;
} public void setWholeTime(int wholeTime) {
this.wholeTime = wholeTime;
} public double getWeightWholeTime() {
return weightWholeTime;
} public void setWeightWholeTime(double weightWholeTime) {
this.weightWholeTime = weightWholeTime;
}
}

运行结果当时间片为 1 时:

时间片为 4 时:

java学习群669823128

Java 实现--时间片轮转 RR 进程调度算法的更多相关文章

  1. 《操作系统_时间片轮转RR进程调度算法》

    转自:https://blog.csdn.net/houchaoqun_xmu/article/details/55540250 时间片轮转RR进程调度算法 一.概念介绍和案例解析时间片轮转法 - 基 ...

  2. Linux常见的进程调度算法

    进程调度:在操作系统中调度是指一种资源分配. 调度算法是指: 根据系统的资源分配策略所规定的资源分配算法. 操作系统管理了系统的有限资源,当有多个进程(或多个进程发出的请求)要使用这些资源时,因为资源 ...

  3. 进程调度算法Linux进程调度算法

    这次介绍一下操作系统的进程调度算法 操作系统的调度分为三种:1.远程调度(创建新进程):2.中程调度(交换功能的一部分):3.短程调度(下次执行哪个进程) 这次讲述的就是短程调度,可以简单的看作咱们平 ...

  4. Linux 常见的进程调度算法

    1.在介绍进程调度之前,先对进程的状态的概念应该有所了解,下面是关于进程状态的一些基本概念:进程的状态分为三种,分别为: 1).运行态:该状态表明进程在实际占用CPU 2).就绪态: 该状态下进程可以 ...

  5. os的进程调度算法(抄袭的)

    package me.letterwish.test; import java.io.BufferedInputStream; import java.io.FileInputStream; impo ...

  6. 2016-2017-2 《Java程序设计》教学进程

    2016-2017-2 <Java程序设计>教学进程 目录 考核方式 课前准备 教学进程 第00周学习任务和要求 第01周学习任务和要求 第02周学习任务和要求 第03周学习任务和要求 第 ...

  7. Java并发编程:进程和线程之由来

    Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够融会贯通 ...

  8. 2015-2016-2 《Java程序设计》教学进程

    2015-2016-2 <Java程序设计>教学进程 目录 考核方式 寒假准备 教学进程 第00周学习任务和要求 第01周学习任务和要求 第02周学习任务和要求 第03周学习任务和要求 第 ...

  9. Java多线程基础:进程和线程之由来

    转载: Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够 ...

随机推荐

  1. 大家一起来学 NHibernate+NUnit (VS2012+SQL Server2008)

    大家一起来学 NHibernate+NUnit (VS2012+SQL Server2008) 分类: C#2013-08-10 18:47 1589人阅读 评论(5) 收藏 举报 NHibernat ...

  2. MAC brew软件安装

    之前一直怀念ubuntu下的apt-get,因为实在是方便,需要安装什么,一个命令搞定,相关的依赖包统统由apt-get维护.下载,编译,安装,那叫一个痛快.什么软件用着不爽,一个命令卸载! 怀念ap ...

  3. mfc学习---文档视图架构

    MFC的AppWizard可以生成三种类型的应用程序:基于对话框的应用.单文档应用(SDI)和多文档应用(MDI).   一般情况下,采用文档/视结构的应用程序至少应由以下对象组成:       1. ...

  4. $python正则表达式系列(4)——分组和后向引用

    分组,即分组匹配,也称为捕获组,是正则中的一种比较重要的匹配方式.此外后向引用和分组相结合,可以写出很多复杂匹配场景的正则. 1. 分组 分组的方法:将子表达式用小括号括起来,如:(exp),表示匹配 ...

  5. toLatin1 toLocal8Bit

    toLatin1.toLocal8Bit都是QString转QByteArray的方法,Latin1代表ASCII,Local8Bit代表unicode

  6. NOIP 合唱队形

    描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…, ...

  7. XamlParseException异常

    一般出现System.Windows.Markup.XamlParseException的错误是由1.dll库加载错误,查询一下你程序中引用的dll你是否加载并引用到程序内.2.程序中引用的文件(tx ...

  8. WPF的外观装饰类——Border

    public class Border : System.Windows.Controls.Decorator 说明:在另一个元素的周围绘制边框.背景或同时绘制二者.

  9. No mojo definitions

    pom.xml <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</gro ...

  10. 《The Cg Tutorial》阅读笔记——动画 Animation

    这段时间阅读了英文版的NVidia官方的<The Cg Tutorial>,借此来学习基本的图形学知识和着色器编程. 在此做一个阅读笔记. 本文为大便一箩筐的原创内容,转载请注明出处,谢谢 ...