优先级调度算法(非抢占式)Java实现

本文详细介绍了Java中的优先级调度算法,包括其基本思想、使用场景及在给定实例中的调度过程。通过分析一个实际的进程列表,展示了如何按照优先级和FCFS原则进行调度,并计算了周转时间和带权周转时间的平均值。
摘要由CSDN通过智能技术生成

Java操作系统进程调度算法------优先级调度算法

一、算法思想

  1. 每个进程都被赋予一个优先级,通常是一个整数值,数值越大表示优先级越高。
  2. 在进程就绪队列中,选择优先级最高的进程进行调度执行。
  3. 如果有多个优先级相同的进程,可以采用先来先服务(FCFS)或轮转调度算法来决定调度顺序。

二、算法分析

假设现在有五个进程先后到达系统进行调度

进程号进程名优先级到达时间服务时间(执行时间)
1001p119:4020
1004p4410:1010
1005p5310:0530
1002p239:5515
1003p329:4525

在优先级调度算法中,由于在9:40时刻系统中只有作业p1,因比系统将优先为作业p1进行调度。作业p1在完成的过程中作业p2、p3、p4、p5先后都到达了系统中。也就是说在作业p1调度完成后系统中会有p2、p3、p4、p5四个作业等待调度。根据优先级高的优先的思想,系统将依次按p2、p4、p5、p3的顺序为接下来的四个作业进行调度。

下述具体的计算可以参考本人FCFS算法的具体内容,此处不过多叙述(操作系统——FCFS算法(Java实现)-CSDN博客

周转时间 = 完成时间 - 到达时间

带权周转时间=周转时间/运行时间
等待时间=周转时间-运行时间(分钟)

平均周转时间
平均等待时间

三、数据结构

作业数据类

class ProcessData {
    //进程号
    public int id;
    //进程名字
    public String name;
    //到达时间
    public LocalTime arriveTime;
    //运行时间
    public double serviceTime;
    //优先级
    public int PRI;
    //开始时间
    public LocalTime startTime;
    //完成时间
    public LocalTime finishTime;
    //周转时间
    public double wholeTime;
    //带权周转时间
    public double weightWholeTime;

    public ProcessData(int id, String name,int PRI,String arriveTime, double serviceTime) {
        this.id = id;
        this.name = name;
        this.PRI = PRI;
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("H:m");
        this.arriveTime = LocalTime.parse(arriveTime,dateTimeFormatter);
        this.serviceTime = serviceTime;
    }

    @Override
    public String toString() {
        DecimalFormat decimalFormat1 = new DecimalFormat("#");
        DecimalFormat format = new DecimalFormat("#.00");
        return id + "\t" +
                name + "\t\t   " +
                PRI + "\t"+
                arriveTime + "\t\t" +
                decimalFormat1.format(serviceTime) + "\t\t\t" +
                startTime + "\t\t\t" +
                finishTime + "\t\t\t" +
                decimalFormat1.format(wholeTime) + "\t\t\t" +
                format.format(weightWholeTime);

    }
}

作业调度(算法实现部分)

package homyit;

import java.text.DecimalFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Scanner;

/**
 * @param:
 * @description: 优先级调度算法(非抢占式)
 * @author: Answer
 * @create:2024/3/22 19:10
 **/
public class YXJ {
    //平均周转时间
    public static double avgWholeTime;
    //平均带权周转时间
    public static double avgWeightWholeTime;

    public static void main(String[] args) {
        boolean answer = true;
        Scanner myScanner = new Scanner(System.in);
        while (answer){
            System.out.print("请输入将要进行的操作:(1:开始进程;-1:结束进程):");
            int condition = myScanner.nextInt();
            if (condition == 1){
                System.out.print("请输入进程个数:");
                int num = myScanner.nextInt();
                ProcessData[] processData = new ProcessData[num];
//                System.out.println( "id\t名字\t到达时间\t执行时间(分钟)" );
                System.out.println( "id \t  名字 \t 优先级\t  到达时间\t   执行时间(分钟)  " );
                for( int i = 0; i < num; i++ ) {
                    processData[i] = new ProcessData
                            (myScanner.nextInt(),
                                    myScanner.next(),
                                    myScanner.nextInt(),
                                    myScanner.next(),
                                    myScanner.nextDouble());
                }
                yxj(processData);
            } else if (condition == -1) {
                answer = false;
                return;
            }else {
                System.out.println("请输入正确操作!");
            }
        }
    }


    //短进程优先调度服务算法实现(非抢占式)
    private static void yxj(ProcessData[] processData){
        avgWholeTime = 0;//平均周转时间
        avgWeightWholeTime = 0;//平均带权周转时间

        //初始化完成的时间,周转时间,带权周转时间的初始化
        for (ProcessData processDatum : processData) {
            processDatum.finishTime = LocalTime.parse("00:00");//设置初始时间为0:00
            processDatum.wholeTime = 0;//设置平均周转时间为0
            processDatum.weightWholeTime = 0;//设置平均带权周转时间为0
            processDatum.hasTime = 0;//初始值为0
        }

        //1.按照到达时间进行排序
        int n = processData.length;
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                if (!timeComparison(processData[j].arriveTime,processData[j + 1].arriveTime)) {
                    // 交换元素
                    ProcessData temp = processData[j];
                    processData[j] = processData[j + 1];
                    processData[j + 1] = temp;
                    if (processData[j].arriveTime.equals(processData[j + 1].arriveTime)) {
                        // 交换元素
                        if (processData[j].serviceTime > processData[j + 1].serviceTime) {
                            ProcessData temp_2 = processData[j];
                            processData[j] = processData[j + 1];
                            processData[j + 1] = temp_2;
                        }
                    }
                    if (processData[j].arriveTime.equals(processData[j + 1].arriveTime) && (processData[j].serviceTime==processData[j + 1].serviceTime )) {
                        // 交换元素
                        if (processData[j].id > processData[j + 1].id) {
                            ProcessData temp_1 = processData[j];
                            processData[j] = processData[j + 1];
                            processData[j + 1] = temp_1;
                        }
                    }

                }

            }
        }

        //2.每个进程运行完成之后,找到当前时刻已经到达的最短进程
        processData[0].startTime = processData[0].arriveTime;
        for (int i = 0; i < n; i++) {
            if (i == 0){
                processData[i].finishTime = processData[i].startTime.plusMinutes((long) processData[i].serviceTime);
            }
            else {
                processData[i].finishTime = processData[i - 1].finishTime.plusMinutes((long) processData[i].serviceTime);
            }
            //2.1查找当前进程执行过程中进入系统的进程
            int m = 0;
            for (int j = i + 1; j < n; j++) {
                if (processData[j].arriveTime.isBefore(processData[i].finishTime) || processData[j].arriveTime.equals(processData[i].finishTime)){
                    m++;
                }
            }
            //2.2processData[i].finishTime时刻已经到达的优先级最高的进程
            if (i != n - 1) {
                int minServiceTimeIndex = getMinServiceTimeIndex(processData, i, m);
                // 交换进程
                ProcessData temp = processData[i + 1];
                processData[i + 1] = processData[minServiceTimeIndex];
                processData[minServiceTimeIndex] = temp;
            }
        }
        run(processData);
        print(processData);
    }

    //算法实现核心
    private static int getMinServiceTimeIndex(ProcessData[] processData, int i, int m) {
        double max = processData[i + 1].PRI;
        int minServiceTimeIndex = i + 1;//用来解决优先权相等的时候交换元素

        for (int k = i + 2; k <= i + m; k++) {
            //优先级高的先执行,如若相等则按FCFS算法来
            if (processData[k].PRI > max ||
                    (processData[k].PRI == max && processData[k].arriveTime.isBefore(processData[minServiceTimeIndex].arriveTime))||
                    (processData[k].PRI == max && processData[k].arriveTime.equals(processData[minServiceTimeIndex].arriveTime) && processData[k].serviceTime < processData[minServiceTimeIndex].serviceTime) ||
                    (processData[k].PRI == max && processData[k].arriveTime.equals(processData[minServiceTimeIndex].arriveTime) && processData[k].serviceTime == processData[minServiceTimeIndex].serviceTime && processData[k].id < processData[minServiceTimeIndex].id)) {
                max = processData[k].PRI;
                minServiceTimeIndex = k;
            }
        }
        return minServiceTimeIndex;
    }


    //运行
    private static void run(ProcessData[] processData){
        for (int i = 0; i < processData.length ; i++) {
            //作业的完成时间为上一个作业的完成时间或者开时时间 + 当前作业的服务时间
            processData[i].finishTime = processData[i].startTime.plusMinutes((long) processData[i].serviceTime);
            //下一个任务的开始时间 = 当前任务的完成时间
            if(i!= processData.length - 1) {
                if(processData[i].finishTime.isBefore(processData[i + 1].arriveTime)){
                    processData[i + 1].startTime = processData[i+ 1 ].arriveTime;
                }
                else {
                    processData[i + 1].startTime = processData[i].finishTime;
                }

            }
            //周转时间 = 完成时间 - 到达时间
            processData[i].wholeTime = ChronoUnit.MINUTES.between(processData[i].arriveTime,processData[i].finishTime);
            //带权周转时间 = 周转时间 / 系统提供的服务时间
            processData[i].weightWholeTime = processData[i].wholeTime / processData[i].serviceTime;
        }
        System.out.println("模拟进程优先级调度过程输出结果:");
    }
    //打印
    private static void print(ProcessData[] processData) {
        System.out.println("ID号\t" + "名字\t" +"优先级\t"+ "到达时间\t" + "  执行时间(分钟)\t" + " 开始时间\t" + "  完成时间\t" + " 周转时间(分钟)\t" + "带权周转时间(系数)\t");
        for (ProcessData processData1 : processData){
            System.out.println(processData1);
            avgWholeTime += processData1.wholeTime;
            avgWeightWholeTime += processData1.weightWholeTime;
        }
        avgWholeTime = avgWholeTime / processData.length;
        avgWeightWholeTime = avgWeightWholeTime / processData.length;
//        DecimalFormat decimalFormat1 = new DecimalFormat("#");
        DecimalFormat decimalFormat2 = new DecimalFormat("#.00");
        String formatAvgWholeTime = decimalFormat2.format(avgWholeTime);
        System.out.println("系统平均周转时间为:" + formatAvgWholeTime);
        String formatAvgWeightWholeTime = decimalFormat2.format(avgWeightWholeTime);

        System.out.println("系统带权平均周转时间为:" + formatAvgWeightWholeTime);
    }


    private static boolean timeComparison(LocalTime time1, LocalTime time2){
        return time1.isBefore(time2);
    }
}

运行结果

在这里插入图片描述

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值