前言
在实现了先来先服务(FCFS)算法之后能够明显的感觉到先来先服务算法将当前处于就绪队列队首的那个进程调度到运行状态。也就是说,先来先服务算法只考虑作业或进程进入就绪队列的时间先后,而不考虑它的下一个CPU周期的长短等其他因素。虽然先来先服务算法简单易行并且是一种非抢占式策略,但性能却不大好导致平均周转时间特别长。因此,在先来先服务的算法基础上提出了短作业优先(SJF)算法来改进先来先服务算法,来减少平均周转时间。本文将介绍如何用Java来简单实现短作业优先调度算法
代码实现
假设当前有四个进程先后到达系统进行调度:
作业名 | 到达时间 | 服务时间 |
A | 0 | 20 |
B | 5 | 15 |
C | 10 | 5 |
D | 15 | 10 |
经过计算可得到如下结果:
作业名 | 到达时间 | 服务时间 | 完成时间 | 周转时间 | 带权周转时间 |
A | 0 | 20 | 20 | 20 | 1 |
B | 5 | 15 | 50 | 45 | 3 |
C | 10 | 5 | 25 | 15 | 3 |
D | 15 | 10 | 35 | 20 | 2 |
平均周转时间: ( 20 + 15 + 20 + 45 ) / 4 = 25
平均带权周转时间:( 20 / 20 + 15 / 5 + 20 / 10 + 45 / 15 ) / 4 = 2.25
接下来编写Java程序,输出以上计算结果
1、作业类
代码如下(示例):
classProcessData { // 到达时间publicintarriveTime; // 服务时间publicintserviceTime; // 完成时间publicintfinishTime; // 周转时间publicintturnTime; // 带权周转时间publicdoublepowerTime; publicProcessData(intarriveTime, intserviceTime) { this.arriveTime=arriveTime; this.serviceTime=serviceTime; } publicStringtoString() { returnarriveTime+"\t"+serviceTime+"\t"+finishTime+"\t"+turnTime+"\t"+powerTime; } }
2、算法实现类
代码如下(示例):
publicclassProcessProject { // 平均周转总时间publicstaticdoubleavgTotalTime; // 平均带权周转时间publicstaticdoubleavgPowerTime; publicstaticvoidmain(String[] args) { ProcessData[] processData=newProcessData[4]; // 定义四个作业processData[0] =newProcessData(0, 20); // 作业AprocessData[1] =newProcessData(5, 15); // 作业BprocessData[2] =newProcessData(10, 5); // 作业CprocessData[3] =newProcessData(15, 10); // 作业D// 短作业优先SJF(processData); } // 短作业优先算法privatestaticvoidSJF(ProcessData[] processData) { intpreFinished=0; // 前一个作业的完成时间即下一个作业的开始时间avgTotalTime=0; // 平均周转时间avgPowerTime=0; // 平均带权周转时间for (inti=0; i<processData.length; i++) { processData[i].finishTime=0; // 设置完成时间为0processData[i].turnTime=0; //周转时间processData[i].powerTime=0; //平均周转时间 } intnumber=0; // 定义作业号// 定义双层for循环用于比较作业的完成时间和服务时间for (inti=0; i<processData.length; i++) { intmin=8888; for (intj=0; j<processData.length; j++) { /*** 1. 如果服务时间小于最小时间* 2. 到达时间小于等于前一个作业的完成时间* 3. 完成时间为0代表着还没有进行服务* 最核心的地方就在于有完成时间限制着作业不会继续重复进入循环*/if (processData[j].serviceTime<min&&processData[j].arriveTime<=preFinished&&processData[j].finishTime==0) { min=processData[j].serviceTime; // 将目前服务时间最短的作业的服务时间赋值给作业的最小完成时间number=j; // 将下一个进行调度的作业号赋值给number } } processData[number].finishTime=preFinished+processData[number].serviceTime; // 当前作业的完成时间等于上一个作业的完成时间加当前作业的服务时间preFinished=processData[number].finishTime; // 将上一个作业的完成时间赋值为当前作业的完成时间processData[number].turnTime=processData[number].finishTime-processData[number].arriveTime; // 周转时间 = 完成时间 - 到达时间processData[number].powerTime=processData[number].turnTime/processData[number].serviceTime; // 带权周转时间 = 周转时间 / 服务时间 } System.out.println("短进程优先算法:"); Display(processData); } // 该方法用于将作业的各种信息进行打印privatestaticvoidDisplay(ProcessData[] processData) { System.out.println("到达时间\t"+"服务时间\t"+"完成时间\t"+"周转时间\t"+"带权周转时间\t"); for (inti=0; i<processData.length; i++) { System.out.println(processData[i]); avgTotalTime+=processData[i].turnTime; // 求总周转时间,此时avgTotalTime中存储的值为总周转时间avgPowerTime+=processData[i].powerTime; // 求总带权周转时间,此时avgPowerTime中存储的值为总带权周转时间 } avgTotalTime=avgTotalTime/processData.length; // 平均周转时间avgPowerTime=avgPowerTime/processData.length; // 平均带权周转时间System.out.println("平均周转时间:"+avgTotalTime); System.out.println("平均带权周转时间:"+avgPowerTime); } }
3、运行结果
总结
以上便是短作业优先调度算法的Java实现,短作业优先算法的核心在于当系统中正在调度一个作业时,在当前作业调度完成之前到达系统的作业将会进行服务时间的比较,服务时间短的作业将在当前作业调度完成后优先进行调度。