轮转法(时间片轮转法)
简介
在轮转算法中,系统根据先来先服务策略,将所有的就绪进程排成一个就绪队列。并可设置每隔一定的时间间隔即可产生一次中断,激活系统中的进程调度程序,完成一次调度,将CPU分配给队首的进程,令其执行。当该进程的时间片结束,或者该进程在时间片上提前结束,系统在将CPU分配给队首的进程。由此,可以保证就绪队列的所有进程在一个确定的时间片内,都能获得一次CPU执行
进程切换的情况
-
在一个时间片内,时间片用尽进程没有结束,这时就要把当前运行的进程放入就绪队列的队尾,就绪队列队首的进程获取到CPU并开始执行
-
在一个时间片内,进程提前结束,这时候此进程运行结束,并且就绪队列的第一进程获取到CPU开始执行。
时间片确定问题
时间片的确定对性能有很大的影响,比如时间片很小,就会出现进程上下文之间频繁切换很影响性能。如果时间片过大,轮转法就退化为了先来先服务算法。
代码演示
首先创建一个Process类来模拟进程,没有lombok包的手动生成getter setter和构造方法即可
package com.xu.demo.ytu;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Process {
//作业名
private String ProcessName;
//到达时间
private int InterTime;
//运行时间
private int WorkTime;
//开始时间
private int StartTime;
//完成时间
private int FinishTime;
//周转时间
private int TurnTime;
//带权周转时间
private float PowerTurnTime;
//时间标识判断是否在时间片上运行结束
private int TimeFlag;
//用于接收用户输入并赋值
public Process(String processName, int interTime, int workTime) {
ProcessName = processName;
InterTime = interTime;
WorkTime = workTime;
TimeFlag= workTime;
}
@Override
public String toString() {
return
"作业名:" + ProcessName +
" 到达时间:" + InterTime +
" 运行时间:" + WorkTime +
" 开始时间:" + StartTime +
" 完成时间:" + FinishTime +
" 周转时间:" + TurnTime +
" 带权周转时间:" + PowerTurnTime
;
}
}
论转算法核心部分代码(这里的时间片为1,可在修改timeSlice进行修改)
package com.xu.demo.ytu;
import java.util.*;
/**
* @Author XuJiAn
* @Time 2022/4/24
*/
public class RR {
/**
* 初始化操作
* @param list 原本的进程数据源程集合
* @param readyQueue 就绪队列
* @return map list与readyQueue结果集映射*
*/
public static Map<String, Object> initProcess(List<Process> list, Deque<Process> readyQueue) {
//将模拟进程按进程的进入时间排序如果进入时间相同按工作时间排序
list.sort(new Comparator<Process>() {
@Override
public int compare(Process p1, Process p2) {
int num = p1.getInterTime() - p2.getInterTime();
return num == 0 ? p1.getWorkTime() - p2.getWorkTime() : num;
}
});
//进程数据源集合移除第一个放入就绪队列
readyQueue.add(list.remove(0));
//操作后的集合存入hashmap返回
Map<String, Object> map = new HashMap<>();
map.put("list", list);
map.put("readyQueue", readyQueue);
return map;
}
/**
* 轮转算法核心方法
* @param list 原本的进程数据源程集合
* @param finishList 结果集
* @param readyQueue 就绪队列
* @param time 时间
* @return finishList 结果集
*/
public static List<Process> doProcess(List<Process> list, List<Process> finishList, Deque<Process> readyQueue, int time) {
int timeSlice = 1;
//要处理的进程
Process process = null;
//存进程名
List<String> rqNames=new ArrayList<>();
if (!readyQueue.isEmpty()) {
process = readyQueue.removeFirst();
//获取开始时间
if (process.getStartTime()==0&&!process.getProcessName().equals("A")) {
process.setStartTime(time);
}
process.setTimeFlag(process.getTimeFlag() - timeSlice);
//判断finish是否还有进程
if (process.getTimeFlag() <= 0) {
if (!list.isEmpty()) {
readyQueue.addLast(list.remove(0));
}
}
}
//进程在时间片上已运行的时间
time = time + timeSlice;
for (Process item : readyQueue) {
rqNames.add(item.getProcessName());
}
// System.out.println("在 ["+(time-timeSlice)+" - "+time+")时间段--"+process.getProcessName()+"----进程正在运行--"+"--就绪队列的进程----"+rqNames);
//进程在时间片上如果没有结束
if (process.getTimeFlag() > 0) {
if (!list.isEmpty()) {
readyQueue.addLast(list.remove(0));
readyQueue.addLast(process);
} else {
readyQueue.addLast(process);
}
}
//进程在时间片上正常结束
if (process.getTimeFlag() == 0) {
process.setFinishTime(time);
process.setTurnTime(process.getFinishTime() - process.getInterTime());
process.setPowerTurnTime((float) process.getTurnTime() / (float) process.getWorkTime());
finishList.add(process);
}
//进程会在时间片没结束的时候提前完成
//在这个时间片内继续处理下一个进程
if (process.getTimeFlag() < 0) {
//这时候process.getTimeFlag()为负数
//此时的time + process.getTimeFlag()就是进程结束时刻
time = time + process.getTimeFlag();
process.setFinishTime(time);
process.setTurnTime(process.getFinishTime() - process.getInterTime());
process.setPowerTurnTime((float) process.getTurnTime() / (float) process.getWorkTime());
finishList.add(process);
}
System.out.println("在 ["+(time-timeSlice)+" - "+time+")时间段--"+process.getProcessName()+"----进程正在运行--"+"--就绪队列的进程----"+rqNames);
//终止条件
if (readyQueue.isEmpty()) {
return finishList;
}
//进行递归
return RR.doProcess(list, finishList, readyQueue, time);
}
}
测试类
package com.xu.demo.ytu;
import java.util.*;
public class TestRR {
public static void main(String[] args) {
Process p1=new Process("A",0,4);
Process p2=new Process("B",1,3);
Process p3=new Process("C",2,4);
Process p4=new Process("D",3,2);
Process p5=new Process("E",4,4);
List<Process> list=new ArrayList<Process>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.add(p5);
//完成的进程放入这个集合
List<Process> finish=new ArrayList<Process>();
//就绪队列
Deque<Process> readyQueue=new ArrayDeque<Process>();
//进行初始化
Map<String, Object> map = RR.initProcess(list, readyQueue);
list = (List<Process>) map.get("list");
readyQueue= (Deque<Process>) map.get("readyQueue");
List<Process> result = RR.doProcess(list, finish, readyQueue, 0);
System.out.println("进程先后完成结果集;");
for (Process process : result) {
System.out.println(process);
}
System.out.println("进程原顺序结果集;");
result.sort(new Comparator<Process>() {
@Override
public int compare(Process p1, Process p2) {
int num = p1.getInterTime() - p2.getInterTime();
return num == 0 ? p1.getWorkTime() - p2.getWorkTime() : num;
}
});
for (Process process : result) {
System.out.println(process);
}
}
}
运行结果
如果时间片为4退化为先来先服务算法