本人是个新手,写下博客用于自我复习、自我总结。
本人编写算法水平不高,可能会有错误,仅供各位参考。
问题描述:
1、 对于给定的一组作业,给出其到达时间和运行时间,例如下表所示:
2、 分别用先来先服务算法、短作业优先和响应比高者优先三种算法给出作业的调度顺序。
3、 计算每一种算法的平均周转时间及平均带权周转时间并比较不同算法的优劣。
模拟:操作系统的作业调度算法
public class JobScheduling {
public static void main(String[] args) {
Job jobA = new Job("A", 0, 6);
Job jobB = new Job("B", 2, 50);
Job jobC = new Job("C", 5, 20);
Job jobD = new Job("D", 5, 10);
Job jobE = new Job("E", 12, 40);
Job jobF = new Job("F", 15, 8);
Job job[] = { jobA, jobB, jobC, jobD, jobE, jobF };
// 先用冒泡排序,将它们按到达时间排序
Bubble(job);
// 先来先服务
FCFS(job);
// 短作业优先
SJF(job);
// 高响应者优先
HRRN(job);
}
// 冒泡排序
static void Bubble(Job job[]) {
Job temp = new Job("", 0, 0); // 临时变量
boolean flag = false; // 标识变量,表示是否进行过交换
for (int i = 0; i < job.length - 1; i++) {
for (int j = 0; j < job.length - 1 - i; j++) {
// 如果前面的数比后面的数大,则交换
if (job[j].arriveTime > job[j + 1].arriveTime) {
flag = true;
temp = job[j];
job[j] = job[j + 1];
job[j + 1] = temp;
}
}
if (!flag) { // 在一趟排序中,一次交换都没有发生过
break;
} else {
flag = false; // 重置flag, 进行下次判断
}
}
}
// 先来先服务算法
static void FCFS(Job job[]) {
double T = 0; // 平均周转时间
double W = 0; // 平均带权周转时间
int finish = 0; // 记录完成时间的变化
double t = 0; // 周转时间
double w = 0; // 带权周转时间
System.out.println("先来先服务算法:");
System.out.print("作业调度顺序:");
for (int c = 0; c < job.length; c++) {
// 记录完成时间的变化
finish = finish + job[c].needTime;
// 计算周转时间
t = finish - job[c].arriveTime;
// 计算带权周转时间
w = t / job[c].needTime;
// 记录周转时间总和
T += t;
// 记录带权周转时间总和
W += w;
System.out.print(job[c].jobName);
}
System.out.println();
System.out.println("平均周转时间为:" + T / 6);
System.out.println("平均带权周转时间为:" + W / 6);
System.out.println("=========================");
}
// 短作业优先算法
static void SJF(Job job[]) {
int finish = job[0].needTime; // 记录完成时间的变化
double t = finish - job[0].arriveTime; // 记录周转时间的变化
double w = t / job[0].needTime; // 记录带权周转时间的变化
double T = t; // 平均周转时间
double W = w; // 平均带权周转时间
int d = 0;// 记录当前选择到的作业号码
int time = 100;// 记录服务时间的变化
int arr[] = { 1, 0, 0, 0, 0, 0 }; // 记录作业的选择情况:1为选中,0为未选中
System.out.println("短作业优先算法:");
System.out.print("作业调度顺序:" + job[0].jobName);
for (int e = 1; e < job.length; e++) {
for (int c = 1; c < job.length; c++) {
/**
* 需要判断:该作业在上一个作业完成时,是否已经到达 该作业是否已经执行完毕 该作业的服务时间是否为最小
* */
if (job[c].arriveTime < finish && arr[c] == 0
&& job[c].needTime < time) {
// 如果满足条件
d = c; // 暂时记录当前作业的下标
time = job[c].needTime; // 暂时记录该作业的服务时间为最小
}
}
arr[d] = 1; // 作业已被调度,设置为1
time = 100;// 重置
// 记录完成时间的变化
finish = finish + job[d].needTime;
// 计算周转时间
t = finish - job[d].arriveTime;
// 计算带权周转时间
w = t / job[d].needTime;
// 记录周转时间总和
T += t;
// 记录带权周转时间总和
W += w;
System.out.print(job[d].jobName);
}
System.out.println();
System.out.println("平均周转时间为:" + T / 6);
System.out.println("平均带权周转时间为:" + W / 6);
System.out.println("=========================");
}
// 响应比高者优先算法
static void HRRN(Job job[]) {
double finish = job[0].needTime; // 记录完成时间的变化
double t = finish - job[0].arriveTime; // 记录周转时间的变化
double w = t / job[0].needTime; // 记录带权周转时间的变化
double T = t; // 平均周转时间
double W = w; // 平均带权周转时间
int d = 0;// 记录当前选择到的作业号码
double time = 0;// 记录响应比
int arr[] = { 1, 0, 0, 0, 0, 0 }; // 记录作业的选择情况:1为选中,0为未选中
System.out.println("响应比高者优先算法:");
System.out.print("作业调度顺序:" + job[0].jobName);
for (int e = 1; e < job.length; e++) {
for (int c = 1; c < job.length; c++) {
// 响应比:(等待时间+要求服务)/要求服务
double response = (finish - job[c].arriveTime + job[c].needTime)
/ job[c].needTime;
/**
* 需要判断:该作业在上一个作业完成时,是否已经到达 该作业是否已经执行完毕 该作业的响应比是否为最大
* */
if (job[c].arriveTime < finish && response > time
&& arr[c] == 0) {
d = c; // 暂时记录当前作业的下标
time = response; // 暂时记录该作业的服务时间为最大
}
}
arr[d] = 1; // 作业已被调度,设置为1
time = 0;// 重置
// 记录完成时间的变化
finish = finish + job[d].needTime;
// 计算周转时间
t = finish - job[d].arriveTime;
// 计算带权周转时间
w = t / job[d].needTime;
// 记录周转时间总和
T += t;
// 记录带权周转时间总和
W += w;
System.out.print(job[d].jobName);
}
System.out.println();
System.out.println("平均周转时间为:" + T / 6);
System.out.println("平均带权周转时间为:" + W / 6);
System.out.println("=========================");
}
}
class Job {
public String jobName; // 作业名
public int arriveTime; // 到达时间
public int needTime; // 服务时间
// 构造器
public Job(String jobName, int arriveTime, int needTime) {
this.jobName = jobName;
this.arriveTime = arriveTime;
this.needTime = needTime;
}
@Override
public String toString() {
return "Job [jobName=" + jobName + ", arriveTime=" + arriveTime
+ ", needTime=" + needTime + "]";
}
}
通过实验结果,可以明显看到这三种算法的优劣:
1、先来先服务算法的每次调度都会从就绪的进程队列中选择一个最先进入该队列的进程,导致先来先服务算法比较有利于长作业,而不利于短作业,也就导致了在三种算法中,平均周转时间和平均带权周转时间最长。
2、短作业优先算法以作业的长短来计算优先级,作业越短,其优先级越高。作业的长短是以作业所要求的运行时间来衡量的。从实验结果来看,该算法效率最高,但它也有缺点:(1)必须预知作业的运行时间。(2)对长作业很不利,也许长作业长期都不会被调度。
3、响应比高者优先算法会根据公式:优先权=(等待时间+要求服务时间)/要求服务时间 来判断。从实验结果来看,该算法效率也比较高,而且有利于短作业,同时能保证每个作业的优先权会根据等待时间的增加而增加,避免了短作业优先算法中长作业长期不会被调度的问题。