实验内容
编写java程序,实现处理机调度的“先来先服务(FCFS)”算法和“短进程优先(SJF)算法”。
要求:
1)随机输入的进程个数、进程名称、进程提交到系统的时间、进程运行所需时间;
2)通过模拟程序,显示以下信息:a)处理机对进程的调度过程。b)这N个进程的平均周转时间;
3)对实验结果截图并辅以文字对运行结果进行分析。
基础知识简介
1、先来先服务(First Come First Served,FCFS)
先来先服务(First Come First Served,FCFS)是一种最简单的调度算法,可以用在进程调度和作业调度中。
它的基本思想是按进程或作业到达的前后顺序进行调度。作业调度中采用该算法时,每次从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源创建进程,然后将进程投入就绪队列。进程调度中采用该算法时,每次从就绪队列中选择一个最先进入该队列的进程,把处理机分配给它,使之投人运行。一直到该进程运行完毕或阻塞后,才让出处理机。
FCFS算法简单。由于它的处理机调度方式是非剥夺方式,因此操作系统不会强行暂停当前正在运行的进程。
FCFS算法的特点如下:
- (1)有利于长作业,不利于短作业。
- (2)有利于处理机繁忙的作业,不利于I/O繁忙的作业。
2、短作业(进程)优先
短作业(进程)优先(Shortest Job First ,SJF 或 Shortest Process Next,SPN)是指对短作业或短进程优先调度的算法。该算法可分别用于作业调度和进程调度。该算法的设计目标是改进FCFS算法,减少作业或进程的平均周转时间。
SJF算法要求作业在开始执行之前预计作业的执行时间,对预计执行时间短的作业优先调人内存。
SPN算法是从就绪队列中选出一个估计运行时间最短的进程,并将处理机分派给它,后来的短进程不能剥夺正在运行的进程。
SJF算法比起FCFS算法有以下优点:
- (1)改善了平均周转时间和平均带权周转时间,缩短了等待时间。
- (2)有利于提高系统的吞吐量。
SJF和SPN算法存在以下缺点:
- (1)对长作业或进程不利。
- (2)该算法没有考虑作业或进程的紧迫程度,因而不能保证紧迫的作业或进程得到及时 处理或响应。
- (3)由于作业或进程的执行时间是用户估计的,因而准确性不高,从而影响调度性能
- (4)如果系统中持续有更短作业或进程出现,可能导致长作业或进程被饿死,即永远得不到执行。
实验过程
1、问题以及设计思路说明:
分别使用先来先服务算法和短进程优先算法对进程进行调度。在过程中,先设计Process进程类,再创建类实现进程CPU中的进程调度,记录下各个进程的调度时间信息,最后进行计算,得出结果。
2、分析说明:
方法generateRandomProcesses()帮助进程随机生成到达时间、运行所需时间。先来先服务算法按照进程提交到系统的顺序进行调度。短进程优先算法中,选择运行时间最短的进程进行调度。在先来先服务算法中对各个进程的到达时间进行排序,在短进程优先中对各进程到达时间和运行时间排序,以此决定先后运行的顺序。最后利用方法calculateAverageTurnaroundTime计算各个算法结果的平均周转时间。
3、实验结果:
两个算法的平均周转时间相比,第二个短进程优先算法的耗时更低。
代码
public class Process {
public String name;
public int arrivalTime;//到达时间
public int burstTime;//运行时间
public int startTime;//开始时间
public int completionTime;//完成时间
public Process(String name, int arrivalTime, int burstTime) {
this.name = name;
this.arrivalTime = arrivalTime;
this.burstTime = burstTime;
}
public String getName() {
return name;
}
public int getArrivalTime() {
return arrivalTime;
}
public int getBurstTime() {
return burstTime;
}
public int getStartTime() {
return startTime;
}
public void setStartTime(int startTime) {
this.startTime = startTime;
}
public int getCompletionTime() {
return completionTime;
}
public void setCompletionTime(int completionTime) {
this.completionTime = completionTime;
}
@Override
public String toString() {
return "Process{" +
"name='" + name + '\'' +
", arrivalTime=" + arrivalTime +
", burstTime=" + burstTime +
", startTime=" + startTime +
", completionTime=" + completionTime +
'}';
}
}
import java.util.*;
public class CPU {
public static void main(String[] args) {
int numProcesses = 5; // 进程个数
List<Process> processes = generateRandomProcesses(numProcesses);
System.out.println("先来先服务算法(FCFS),进程调度顺序:");
fcfs(processes);
double avgTurnaroundTime1 = calculateAverageTurnaroundTime(processes);
System.out.println("\n平均周转时间:" + avgTurnaroundTime1);
System.out.println("\n短进程优先算法(SJF),进程调度顺序:");
sjf(processes);
double avgTurnaroundTime = calculateAverageTurnaroundTime(processes);
System.out.println("\n平均周转时间:" + avgTurnaroundTime);
}
// 生成随机的进程
public static List<Process> generateRandomProcesses(int numProcesses) {
List<Process> processes = new ArrayList<>();
Random random = new Random();
for (int i = 1; i <= numProcesses; i++) {
String name = "p" + i;
int arrivalTime = random.nextInt(10); // 进程提交到系统的时间(0-9之间的随机数)
int burstTime = random.nextInt(10) + 1; // 进程运行所需时间(1-10之间的随机数)
Process process = new Process(name, arrivalTime, burstTime);
processes.add(process);
}
return processes;
}
// 先来先服务(FCFS)算法
public static void fcfs(List<Process> processes) {
Collections.sort(processes, Comparator.comparing(Process::getArrivalTime));
int preFinished = 0; // 前一个作业的完成时间
// // 如果第一个作业的到达时间不等于前一个作业的完成时间,就将前一个作业的完成时间定义为当前作业的到达时间
// if (processes.get(0).arrivalTime != preFinished) {
// preFinished = processes.get(0).arrivalTime;
// }
//
// for (Process value : processes) {
// // 作业的完成时间为上一个作业的完成时间加当前作业的服务时间
// value.completionTime = preFinished + value.burstTime;
// preFinished = value.completionTime;
// }
int currentTime = 0;
for (Process process : processes) {
process.setStartTime(Math.max(currentTime, process.getArrivalTime()));
currentTime = process.getStartTime() + process.getBurstTime();
process.setCompletionTime(currentTime);
System.out.println("进程 " + process.getName() + " 到达时间: " + process.arrivalTime + " 调度时间:"
+ process.getStartTime() + "-" + process.getCompletionTime() );
}
}
// 短进程优先(SJF)算法
public static void sjf(List<Process> processes) {
Collections.sort(processes, Comparator.comparing(Process::getArrivalTime).thenComparing(Process::getBurstTime));
int currentTime = 0;
for (Process process : processes) {
process.setStartTime(Math.max(currentTime, process.getArrivalTime()));
currentTime = process.getStartTime() + process.getBurstTime();
process.setCompletionTime(currentTime);
System.out.println("进程 " + process.getName() + " 到达时间: " + process.arrivalTime+ " 调度时间:"
+ process.getStartTime() + "-" + process.getCompletionTime());
}
}
// 计算平均周转时间
public static double calculateAverageTurnaroundTime(List<Process> processes) {
int totalTurnaroundTime = 0;
for (Process process : processes) {
int turnaroundTime = process.getCompletionTime() - process.getArrivalTime();
totalTurnaroundTime += turnaroundTime;
}
return (double) totalTurnaroundTime / processes.size();
}
}
参考文献:郁红英;王磊;武磊;李春强. 计算机操作系统[M]. 第三版. 清华大学出版社, 2018年.