zoukankan      html  css  js  c++  java
  • 操作系统常见的进程调度算法

    1.先来先服务

           (FCFS: first come first service)总是把当前处于就绪队列之首的那个进程调度到运行状态。也就说,它只考虑进程进入就绪队列的先后,而不考虑它的其他因素。FCFS算法简单易行,是一种非抢占式策略,但性能却不大好。只考虑他的到达时间来决定他的执行顺序。

    private void FCFS() {
    
    //        按提交时间排序得到新的序列
            float[] arr = new float[size];
            Processcourse[] tmp = new Processcourse[size];
            for (int i = 0; i < size ; i++) {
                arr[i] = work[i].submitTime;
            }
            Arrays.sort(arr);
            for (int i = 0; i < size ; i++) {
                for (int j = 0; j < size ; j++) {
                    if(arr[i] == work[j].submitTime){
                        tmp[i] = work[j];
                    }
                }
            }
            work = tmp;
    
    
            //得到第一个的任务的全部时间
            work[0].startTime = work[0].submitTime;
            work[0].finishTime = work[0].submitTime + work[0].runTime;
           //求出每个的开始时间和结束时间
            for (int j = 1; j < this.size; j++) {
                if(work[j].submitTime <= work[j-1].finishTime){//判断后面进程是否到来
                work[j].startTime = work[j-1].finishTime;
                work[j].finishTime = work[j].startTime+work[j].runTime;
                }else{
                    work[j].startTime = work[j].submitTime;
                    work[j].finishTime = work[j].startTime+work[j].runTime;
                }
            }
            //求出周转时间和带权周转时间
            for (int j = 0; j < this.size; j++) {
                work[j].turnoverTime = work[j].finishTime - work[j].submitTime;
                work[j].wtTime = work[j].turnoverTime/work[j].runTime;
            }
            System.out.println("运行顺序:");
            for (int i = 0; i < this.size; i++) {
                System.out.print(work[i].workName+" ");
            }
            System.out.println();
            System.out.println("作业"+"	"+"提交时间"+"	"+"运行时间"+"	"+"开始时间"+"	"+"结束/完成时间"+"	"+"周转时间"+"	"+"带权周转时间");
            for (int i = 0; i < this.size; i++) {
                //小数点后保留一位,并且四舍五入
                System.out.println(work[i].workName+"    "+work[i].submitTime+"      "+work[i].runTime+"      "+work[i].startTime+"      "
                        +work[i].finishTime+"      "+(float)(Math.round(work[i].turnoverTime*10))/10+"      "+(float)(Math.round(work[i].wtTime*10))/10);
            }
    
            float sumturnTime = 0;
            float sumwtfTime = 0;
            for (int i = 0; i < this.size; i++) {
                sumturnTime+= work[i].turnoverTime;
                sumwtfTime+= work[i].wtTime;
            }
            System.out.println("平均周转时间:"+(float)(Math.round((sumturnTime/size)*100))/100+" "+"平均带权周转时间:"+(float)(Math.round((sumwtfTime/size)*100))/100);
    
        }
    

      测试用例:

    1  8.5  0.5  1
    2  8.0  1.0  1
    3  9.0  0.2  2
    4  9.1  0.1  3

    运行结果:

    2.短作业优先

          (SJF, Shortest Job First),对预计执行时间短的作业(进程)优先分派处理机。 再不考虑抢占的前提下,判断进程到达时间是否小于上一个进程的完成时间,进入等待序列,然后找到等待序列的完成所要时间最短的进程。

        private void SJF() {
    
            //按提交时间排序得到新的序列
            float[] arr = new float[size];
            Processcourse[] tmpArr = new Processcourse[size];
            for (int i = 0; i < size ; i++) {
                arr[i] = work[i].submitTime;
            }
            //排序提交时间
            Arrays.sort(arr);
            //重新赋值
            for (int i = 0; i < size ; i++) {
                for (int j = 0; j < size ; j++) {
                    if(arr[i] == work[j].submitTime){
                        tmpArr[i] = work[j];
                    }
                }
            }
            work = tmpArr;
    
            //得到第一个的任务的开始时间和完成时间
            work[0].startTime = work[0].submitTime;
            work[0].finishTime = work[0].submitTime + work[0].runTime;
    
            //存入第一个进程完成时间
            float tmpfinshTime = work[0].finishTime;
    
            //等待序列
            Processcourse[] wait = new Processcourse[this.size];
            //运行完成序列
            Processcourse[] finish  = new Processcourse[this.size];
            int finNum = 0;//完成序列的个数
            int index = 1;//下标从数组的一号位置开始
    
            System.out.println("运行进程:");
            System.out.println(work[0].workName);
            for (int j = 0; j < size-1; j++) {
            int num = 0;   //等待
            int k = 1;
    
            //等待序列
              System.out.println("等待进程:");
            for (int i = 1; i < this.size; i++) {
                if(work[i]!=null && work[i].submitTime <= tmpfinshTime){
                    wait[k] = work[i];
                    k++;
                    num++;
                }
            }
            //遍历等待序列
                for (int i = 1 ; i <= num; i++) {
                    System.out.print(wait[i].workName+" ");
                }
                System.out.println();
    
            float min = 0.0f;
            //找到等待序列的最小运行时间
                min = wait[1].runTime;
            for (int i = 1; i <= num; i++) {
                    if (wait[i].runTime < min) {
                        min = wait[i].runTime;
                    }
            }
            for (int i = 1; i < size ; i++) {
                if(work[i] != null && work[i].runTime == min){
                    work[i].startTime = tmpfinshTime;
                    work[i].finishTime = work[i].startTime+work[i].runTime;
                    //更新完成时间
                    tmpfinshTime = work[i].finishTime;
                    finish[index++] = work[i];
                    finNum++;
                    work[i] = null;
                }
            }
    
                //输出运行过的进程
                System.out.println("运行进程:");
                System.out.println(finish[finNum].workName);
        }
    
        //将临时值放回原数组
            for (int i = 1; i <= finNum; i++) {
                work[i] = finish[i];
            }
            
    
                //求出周转时间和带权周转时间
                for (int i = 0; i < this.size; i++) {
                    work[i].turnoverTime = work[i].finishTime - work[i].submitTime;
                    work[i].wtTime = work[i].turnoverTime / work[i].runTime;
                }
    
                System.out.println("作业" + "	" + "提交时间" + "	" + "运行时间" + "	" + "开始时间" + "	" + "结束/完成时间" + "	" + "周转时间" + "	" + "带权周转时间");
                for (int i = 0; i < this.size; i++) {
                    //小数点后保留一位,并且四舍五入
                    System.out.println(work[i].workName + "    " + work[i].submitTime + "      " + work[i].runTime + "      " + work[i].startTime + "      "
                            + work[i].finishTime + "      " + (float) (Math.round(work[i].turnoverTime * 10)) / 10 + "      " + (float) (Math.round(work[i].wtTime * 10)) / 10);
                }
            float sumturnTime = 0;
            float sumwtfTime = 0;
            for (int i = 0; i < this.size; i++) {
                sumturnTime+= work[i].turnoverTime;
                sumwtfTime+= work[i].wtTime;
            }
            System.out.println("平均周转时间:"+(float)(Math.round((sumturnTime/size)*100))/100+"  "+"平均带权周转时间:"+(float)(Math.round((sumwtfTime/size)*100))/100);
            }

    测试用例:

    1  8.5  0.5  1
    2  8.0  1.0  1
    3  9.0  0.2  2
    4  9.1  0.1  3

    运行结果:

    3.高响应比优先

           高响应比优先调度算法(Highest Response Ratio Next)是一种对CPU中央控制器响应比的分配的一种算法。HRRN是介于FCFS(先来先服务算法)与SJF(短作业优先算法)之间的折中算法,既考虑作业等待时间又考虑作业运行时间,既照顾短作业又不使长作业等待时间过长,改进了调度性能。

           响应比 =(等待时间+要求服务时间)/ 要求服务时间

    private void HRRN() {
            //按提交时间排序得到新的序列
            float[] arr = new float[size];
            Processcourse[] tmpArr = new Processcourse[size];
            for (int i = 0; i < size; i++) {
                arr[i] = work[i].submitTime;
            }
            //排序提交时间
            Arrays.sort(arr);
            //重新赋值
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    if (arr[i] == work[j].submitTime) {
                        tmpArr[i] = work[j];
                    }
                }
            }
            work = tmpArr;
    
            //得到第一个的任务的开始时间和完成时间
            work[0].startTime = work[0].submitTime;
            work[0].finishTime = work[0].submitTime + work[0].runTime;
    
            //存入第一个进程完成时间
            float tmpfinshTime = work[0].finishTime;
    
            //等待序列
            Processcourse[] wait = new Processcourse[this.size];
            //运行完成序列
            Processcourse[] finish = new Processcourse[this.size];
            int finNum = 0;//等待序列的个数
            int index = 1;//下标从数组的一号位置开始
    
            System.out.println("运行顺序如下:");
            System.out.println("运行进程:");
            System.out.println(work[0].workName);
    
            //运行的次数
            for (int j = 1; j < size; j++) {
                int num = 0;
                int k = 1;
    
                //等待序列
                System.out.println("等待进程:");
                for (int i = 1; i < this.size; i++) {
                    if (work[i] != null && work[i].submitTime <= tmpfinshTime) {
                        wait[k] = work[i];
                        k++;
                        num++;
                    }
                }
                //遍历等待序列
                for (int i = 1; i <= num; i++) {
                    System.out.print(wait[i].workName + " ");
                }
                System.out.println();
    
                //找到等待序列的最高优先级
                float max = 0.0f;
                float waitTime = 0.0f;
                float tmp2 = 0.0f;//记录响应比
    //            Processcourse[] tmp1 = new Processcourse[this.size];
                String tmpName = null;
                for (int i = 1; i <= num; i++) {
                    waitTime =tmpfinshTime - wait[i].submitTime;
                    tmp2 = 1.0F+(waitTime/wait[i].runTime);
                    wait[i].priority = tmp2;
                    max = (1.0f+((tmpfinshTime - wait[1].submitTime)/wait[1].runTime));
                    if(tmp2 > max){
                       max = (1.0f+(waitTime/wait[i].runTime));
                        tmpName = wait[i].workName;
                    }else {
                        tmpName = wait[1].workName;
                    }
                }
    
    
    
                for (int i = 1; i < this.size; i++) {
                    if(work[i] != null && tmpName.equals(work[i].workName)){
                        work[i].priority = max;
                    }
                }
            //tmp1置空
    //            tmp1 = null;
                for (int i = 1; i < size; i++) {
                    if (work[i] != null && work[i].priority == max) {
                        work[i].startTime = tmpfinshTime;
                        work[i].finishTime = work[i].startTime + work[i].runTime;
                        //更新完成时间
                        tmpfinshTime = work[i].finishTime;
                        //更新
                        finish[index++] = work[i];
                        finNum++;
                        work[i] = null;
                    }
                }
    
                //输出运行过的进程
                System.out.println("运行进程:");
                System.out.println(finish[finNum].workName);
            }
    
            //将临时值放回原数组
            for (int i = 1; i <= finNum; i++) {
                work[i] = finish[i];
            }
            
    
            //求出周转时间和带权周转时间
            for (int i = 0; i < this.size; i++) {
                work[i].turnoverTime = work[i].finishTime - work[i].submitTime;
                work[i].wtTime = work[i].turnoverTime / work[i].runTime;
            }
    
            System.out.println("作业" + "	" + "提交时间" + "	" + "运行时间" + "	" + "开始时间" + "	" + "结束/完成时间" + "	" + "周转时间" + "	" + "带权周转时间"+"	"+"响应比");
            for (int i = 0; i < this.size; i++) {
                //小数点后保留一位,并且四舍五入
                System.out.println(work[i].workName + "    " + work[i].submitTime + "      " + work[i].runTime + "      " + work[i].startTime + "      "
                        + work[i].finishTime + "      " + (float) (Math.round(work[i].turnoverTime * 100)) / 100 + "      " + (float) (Math.round(work[i].wtTime * 100)) / 100+"     "+(float) (Math.round(work[i].priority* 100)) / 100);
            }
            float sumturnTime = 0;
            float sumwtfTime = 0;
            for (int i = 0; i < this.size; i++) {
                sumturnTime += work[i].turnoverTime;
                sumwtfTime += work[i].wtTime;
            }
            System.out.println("平均周转时间:" + (float) (Math.round((sumturnTime / size) * 100)) / 100 + "  " + "平均带权周转时间:" + (float) (Math.round((sumwtfTime / size) * 100)) / 100);
        }

    测试用例:

    1  8.5  0.5  1
    2  8.0  1.0  1
    3  9.0  0.2  2
    4  9.1  0.1  3

    运行结果:

    4.时间片轮转法

        时间片轮转(RR)是一种最古老,最简单,最公平且使用最广的算法。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。

        private void RR() {
            System.out.println("请输入时间片的大小:");
            float fTime = sc.nextFloat();//时间片大小
            if(fTime <= 0 ){
                System.out.println("无效输入");
                return;
            }
    
            //按提交时间排序得到新的序列
            float[] arr = new float[size];
            Processcourse[] tmpArr = new Processcourse[size];
            for (int i = 0; i < size; i++) {
                arr[i] = work[i].submitTime;
            }
            //排序提交时间
            Arrays.sort(arr);
            //重新赋值
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    if (arr[i] == work[j].submitTime) {
                        tmpArr[i] = work[j];
                    }
                }
            }
            work = tmpArr;
            //方便再次调用
            for (int i = 0; i < this.size; i++) {
                work[i].flag = false;
            }
            //无该过程最终运行时间全为0.0(最终重新赋值给work)
            float tempRunTime[] = new float[this.size];
            for (int i = 0; i < this.size; i++) {
                tempRunTime[i] = work[i].runTime;
            }
    
            //等待序列
            Processcourse[] wait = new Processcourse[100];
            int num = 1;   //等待序列个数(开始默认一个)
    
            //运行完成序列
            Processcourse[] finish  = new Processcourse[this.size];
            int number = 0;  //完成个数
            //当前切换的时间
            float nowTime = work[0].submitTime;  //记录进程开始时间
            float overTime = 0;  //记录进程出来时间
    
            wait[0] = work[0];
            work[0].flag = true;//标记其已经进入等待序列(false么有进入过,true进入过,相当于原数组的元素只进入一次就绪队列,接下来的的其结束与否只在等待序列中判断)
            String tmpName = null;
    
            //临时记录在上一个么有完成的进程
            Processcourse[] tmpWait = new Processcourse[1];
    
            System.out.println("时刻:"+nowTime+" 进程:"+work[0].workName+" 开始运行");
            int k= 0;
            int stopFlag = 0;
            //当作业么有运行完,一直执行
            while (stopFlag != this.size){
                //当前任务么有运行完
                if(wait[k]!=null) {
                    if (wait[k].runTime > fTime) {
                        wait[k].runTime -= fTime;
                        //更新当前还需要运行的时间
                        nowTime += fTime;//更新当前时间
                        System.out.println("时刻:" + nowTime + " 进程:" + wait[k].workName + " 停止运行,进入就绪队列");
                        tmpWait[0] = wait[k];
                    } else {
                        nowTime += wait[k].runTime;
                        wait[k].runTime = 0;//说明运行结束
                        tmpName = wait[k].workName;
                        overTime = nowTime;
                        System.out.println("时刻:" + overTime + " 进程:" + wait[k].workName + " 运行结束");
                    }
                }
                //如果等待序列里面其运行结束,将原数组直null,方便不去判断,并且完成数加一
                for (int j = 0; j < this.size; j++) {
                    if(work[j] != null && tmpName!= null && tmpName.equals(work[j].workName)){//让运行过得不能排在么运行的前面
                        work[j].finishTime = overTime;
    //                    work[j].turnoverTime = overTime - work[j].submitTime;
    //                    work[j].wtTime = (work[j].turnoverTime/work[j].runTime);
                        finish[number++] = work[j];
                        work[j] = null;
                        stopFlag++;
                    }
                }
    
                //判断进入等待序列
                for (int j = 0; j < this.size; j++) {
                    if((work[j] != null)  && (work[j].submitTime <= nowTime) && (work[j].flag == false) ){
                        wait[num++] = work[j];
                        work[j].flag = true;
                    }
                }
    
                if(tmpWait[0] != null) {
                    wait[num++] = tmpWait[0];
                }
                    tmpWait[0] = null;
                k++;
    
            }
    
           wait = null;
            //将其放回原work数组
            for (int i = 0; i < this.size; i++) {
                work[i] = finish[i];
            }
    
            //按提交时间排序得到新的序列
            float[] arr1 = new float[size];
            Processcourse[] tmpArr1 = new Processcourse[size];
            for (int i = 0; i < size; i++) {
                arr1[i] = work[i].submitTime;
            }
            //排序提交时间
            Arrays.sort(arr1);
            //重新赋值
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    if (arr1[i] == work[j].submitTime) {
                        tmpArr1[i] = work[j];
                    }
                }
            }
            work = tmpArr1;
    
            //还原其初始运行时间
            for (int i = 0; i < this.size ; i++) {
                work[i].runTime = tempRunTime[i];
            }
    
            //求出周转时间和带权周转时间
            for (int i = 0; i < this.size; i++) {
                work[i].turnoverTime = work[i].finishTime - work[i].submitTime;
                work[i].wtTime = work[i].turnoverTime / work[i].runTime;
            }
    
            System.out.println("作业" + "	" + "提交时间" + "	" + "运行时间" +  "	" + "结束/完成时间" + "	" + "周转时间" + "	" + "带权周转时间");
            for (int i = 0; i < this.size; i++) {
                //小数点后保留一位,并且四舍五入
                System.out.println(work[i].workName + "    " + work[i].submitTime + "      " + work[i].runTime +  "      "
                        + work[i].finishTime + "      " + (float) (Math.round(work[i].turnoverTime * 100)) / 100 + "      " + (float) (Math.round(work[i].wtTime * 100)) / 100);
            }
            float sumturnTime = 0;
            float sumwtfTime = 0;
            for (int i = 0; i < this.size; i++) {
                sumturnTime += work[i].turnoverTime;
                sumwtfTime += work[i].wtTime;
            }
            System.out.println("平均周转时间:" + (float) (Math.round((sumturnTime / size) * 100)) / 100 + "  " + "平均带权周转时间:" + (float) (Math.round((sumwtfTime / size) * 100)) / 100);
    
        }

    测试用例:

    p1  0  5  1
    p2  2  4  1
    p3  4  1  1
    p4  5  6  1

    运行结果:

    进程类:

    public class Processcourse {
        String workName;//作业
        float submitTime; //提交时间
        float runTime;//运行时间
        float startTime;//开始时间
        float finishTime;  //完成时间
        float turnoverTime;//周转时间
        float wtTime;   //带权周转时间
        float priority;  //响应比
        float prior;     //优先级
        boolean flag;   //标记
    
        public Processcourse(String work, float submitTime, float runTime,float prior) {
            this.workName = work;
            this.submitTime = submitTime;
            this.runTime = runTime;
            this.prior = prior;
        }
    
        @Override
        public String toString() {
            return "Processcourse{" +
                    "workName=" + workName +
                    ", submitTime=" + submitTime +
                    ", runTime=" + runTime +
                    ", startTime=" + startTime +
                    ", finishTime=" + finishTime +
                    ", turnoverTime=" + turnoverTime +
                    ", wtTime=" + wtTime +
                    ",priority=" + priority+
                    "prior="+prior+
                    ",flag="+flag+
                    '}';
        }
    
    }

    初始化以及main函数类:

    public class Control {
        private Processcourse[] work;
        int maxWork = 100;
        int size; //真实作业个数
        private Scanner sc;
        public Control() {
          this.work = new Processcourse[maxWork];
          this.sc = new Scanner(System.in);
        }
    
        public static void main(String[] args) {
            Control con = new Control();
            con.start();//程序入口
        }
    
        private void start() {
            System.out.println("===================================");
            System.out.println("欢迎来到本系统");
            //初始化
            System.out.println("请输入进程的个数:" );
            int num = sc.nextInt();
            System.out.println("请依次输入进程号,提交时间,运行时间,优先级(中间用空格隔开):");
            int i = 0;
            while(i < num){
                String workName = sc.next();//作业名
                float submitTime = sc.nextFloat(); //提交时间
                float runTime = sc.nextFloat();//运行时间
                float  prior = sc.nextFloat();//优先级
                if(i == size){
                    this.work[this.size++] = new Processcourse(workName,submitTime,runTime,prior);
                }
                i++;
            }
            for (; ; ) {
                System.out.println("请选择进程调度方法:");
                System.out.println("1.先来先服务法");
                System.out.println("2.短作业优先法");
                System.out.println("3.高响应比法");
                System.out.println("4.时间片轮转法");
                System.out.println("5.高优先级法");
                System.out.println("6.退出");
                System.out.println("===================================");
                int ch = sc.nextInt();
                switch (ch){
                    case 1:
                        FCFS();
                        break;
                    case 2:
                        SJF();
                        break;
                    case 3:
                        HRRN();
                        break;
                    case 4:
                        RR();
                        break;
                    case 5:
                        PSA();
                        break;
                    case 6:
                        System.out.println("再见");
                        return;
                        default:
                            System.out.println("无效输入,请重新输入!");
                }
            }
        }

            以上便是除了高优先级的(高优先级同短作业优先代码类似)全部代码,由于采用数组代码比较冗长,输出函数可以单独写一个方法封装,也可以减少代码量,但是由于当时图方便,直接将第一个写的粘贴修改输出,自己可以将其封装。

      

  • 相关阅读:
    向iphone模拟器中导入图片
    键盘样式风格设置及隐藏
    (转)iPhone图片处理:摄像头/相册获取图片,压缩图片,上传服务器,下载,拉伸,方法总结
    python通过get方式,post方式发送http请求和接收http响应-urllib urllib2
    Python中 如何使用telnet 检测端口是否通
    Linux运维人员共用root帐户权限审计
    python ssh登录
    欢迎来到 Flask 的世界
    大杂烩
    随笔
  • 原文地址:https://www.cnblogs.com/128-cdy/p/12187875.html
Copyright © 2011-2022 走看看