前几天用java做了实现一下SPF短进程优先调度算法,在这里分享一下我的代码
算法描述
这是我的进程类
public class JCB implements Comparable<JCB>{
public int name; //进程名
public double atime; //进程提交时间
public double time; //进程执行时间
public double rtime; //进程开始时间
public double otime; //进程完成时间
public double total; //周转时间
public double ptotal; //带权周转时间(周转系数)
}
这是运行主类
我的实现思想就是,先判断有无进程到达,有的会就找执行时间最短的,没有的话就时间往后退,就是找到提交时间最短的未执行的进程,然后让时间等于它的提交时间,执行这个进程。我这边采用的是执行完进程就删除这个进程,当然也可以用一个属性表示是否完成,不过这样就要多加一些判断了。
public class Main02{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入进程数");
int cnt=sc.nextInt();
List<JCB> jcbs=new ArrayList<JCB>();
System.out.println("请一次输入"+cnt+"个提交时间和执行时间");//赋值
for(int i=0;i<cnt;i++) {
JCB jcb=new JCB();
jcb.name=i+1;
jcb.atime=sc.nextDouble();
jcb.time=sc.nextDouble();
jcbs.add(jcb);
}
double now=0.0;double sum1=0.0;double sum2=0.0;
int flag=-1;int tag=0;
System.out.println("进程名\t提交时间\t执行\t开始\t完成\t周转\t带权周转");
while(jcbs.size()>0) {
for (int c = 0; c < jcbs.size(); c++) {//判断是否有到了的
if (jcbs.get(c).atime <= now ) {
// 如果满足条件
flag = c; // 暂时记录当前作业的下标
}
}
if(flag==-1) {
tag=findMInFlag(jcbs);
flag=-2;
now = jcbs.get(tag).atime;
}
JCB temp =new JCB();
int index;
if(flag==-2) {
index=tag;
}else {
index=findMin(jcbs,now);
}
flag=-1;
jcbs.get(index).rtime=now;
temp=jcbs.get(index);
temp.otime=temp.rtime+temp.time;
now =temp.otime;
temp.total=temp.otime-temp.atime;
temp.ptotal=temp.total/temp.time;
//我这里用大数类BigDecimal去两位小数是为了在保持double的精度,顺便缩短数的长度
temp.atime=new BigDecimal(temp.atime).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
temp.rtime=new BigDecimal(temp.rtime).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
temp.total = new BigDecimal(temp.total).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
temp.ptotal = new BigDecimal(temp.ptotal).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
temp.otime = new BigDecimal(temp.otime).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
sum1+=temp.total;
sum2+=temp.ptotal;
System.out.println(temp.name+"\t"+temp.atime+"\t"+temp.time+"\t"+temp.rtime+"\t"+temp.otime+"\t"+temp.total+"\t"+temp.ptotal);
jcbs.remove(index);//执行完后删除
}
sum1 = new BigDecimal(sum1).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
sum2 = new BigDecimal(sum2).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
// System.out.println("平均周转时间"+sum1/cnt+"\t带权周转时间"+sum2/cnt);
sum1 = new BigDecimal(sum1/cnt).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
sum2 = new BigDecimal(sum2/cnt).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
System.out.println("取两位小数");
System.out.println("平均周转时间"+sum1+"\t平均带权周转时间"+sum2);
}
public static int findMin(List<JCB> jcbs,double now) {//找到到达的进程中执行时间最短的进程编号
int minIndex=0;
for(int i=0;i<jcbs.size();i++) {
if(jcbs.get(i).time<jcbs.get(minIndex).time && jcbs.get(i).atime<=now) {
minIndex=i;
}
}
return minIndex;
}
//这是一个找最早提交时间的函数
public static int findMInFlag(List<JCB> jcbs) {//找到提交时间最早的进程编号
int minIndex=0;
for(int i=0;i<jcbs.size();i++) {
if(jcbs.get(i).atime<jcbs.get(minIndex).atime ) {
minIndex=i;
}
}
return minIndex;
}
}
还有另外的这个算法是用的先按提交时间排序,这样就不用再去找提交时间最早的进程了。
代码附上
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入进程数");
int cnt=sc.nextInt();
List<JCB> jcbs=new ArrayList<JCB>();
System.out.println("请一次输入"+cnt+"个提交时间和执行时间");//赋值
for(int i=0;i<cnt;i++) {
JCB jcb=new JCB();
jcb.name=i+1;
jcb.atime=sc.nextDouble();
jcb.time=sc.nextDouble();
jcbs.add(jcb);
}
Collections.sort(jcbs);
for (JCB jcb : jcbs) {
System.out.println(jcb.atime+" "+jcb.time);
}
double now=0.0;
double sum1=0.0;
double sum2=0.0;
System.out.println("作业名\t提交时间\t执行\t开始\t完成\t周转\t带权周转");
int flag=0;
while(jcbs.size()>0) {
JCB temp =new JCB();
if(jcbs.get(0).atime>now) {
jcbs.get(0).rtime=jcbs.get(0).atime;
temp=jcbs.get(0);
temp.otime=temp.rtime+temp.time;
now=temp.otime;
}else {
int index=findMin(jcbs,now);
jcbs.get(index).rtime=now;
temp=jcbs.get(index);
temp.otime=temp.rtime+temp.time;
now =temp.otime;
flag=index;
}
temp.otime=temp.rtime+temp.time;
temp.total=temp.otime-temp.atime;
temp.ptotal=(float)temp.total/(float)temp.time;
temp.atime=new BigDecimal(temp.atime).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
temp.rtime=new BigDecimal(temp.rtime).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
temp.total = new BigDecimal(temp.total).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
temp.ptotal = new BigDecimal(temp.ptotal).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
temp.otime = new BigDecimal(temp.otime).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
sum1+=temp.total;
sum2+=temp.ptotal;
System.out.println(temp.name+"\t"+temp.atime+"\t"+temp.time+"\t"+temp.rtime+"\t"+temp.otime+"\t"+temp.total+"\t"+temp.ptotal);
jcbs.remove(flag);
}
sum1 = new BigDecimal(sum1).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
sum2 = new BigDecimal(sum2).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
System.out.println("平均周转时间"+sum1/cnt+"\t带权周转时间"+sum2/cnt);
sum1 = new BigDecimal(sum1/cnt).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
sum2 = new BigDecimal(sum2/cnt).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
System.out.println("取两位小数");
System.out.println("平均周转时间"+sum1+"\t带权周转时间"+sum2);
}
public static int findMin(List<JCB> jcbs,double now) {
int minIndex=0;
for(int i=0;i<jcbs.size();i++) {
if(jcbs.get(i).time<jcbs.get(minIndex).time && jcbs.get(i).atime<=now) {
minIndex=i;
}
}
return minIndex;
}
}
```int minIndex=0;
for(int i=0;i<jcbs.size();i++) {
if(jcbs.get(i).time<jcbs.get(minIndex).time && jcbs.get(i).atime<=now) {
minIndex=i;
}
}
return minIndex;
}
}