進程調度 RR 時間片輪轉調度 java python實現


時間片輪轉調度 RR

時間片輪轉調度策略:在輪轉(RR)法中,系統將所有的就緒進程按FCFS策略排成一個就緒隊列。系統可設置每隔一定時間(如30 ms)便產生一次中斷,去激活進程調度程序進行調度,把CPU分配給隊首進程,並令其執行一個時間片。當它運行完畢后,又把處理機分配給就緒隊列中新的隊首進程,也讓它執行一個時間片。這樣,就可以保證就緒隊列中的所有進程在確定的時間段內,都能獲得一個時間片的處理機時間。

數據結構和符號說明

本次的PCB類數據結構有三個公共變量,五個私有變量,一個標志變量,以及一個時時返回給調度函數值的交互式變量。

//三個公共變量:作業名、到達時間、服務時間
String threadName; int timeArrival; int timeSever;
//五個私有變量:計算專用服務時間、開始執行時間、完成時間、周轉時間、帶權周轉時間
private int timeSeverFor; private int timeStart; private int timeComplete;
private int timeTurnaround; private double timeWeightedTurnaround;
//一個標志:表示是否還需要調度 一個交互式變量:表示自己本次使用了多少時間
private boolean isFinish = false; private int timeUse;

另有setter、getter函數實現私有變量的訪問,同時有一個public boolean isNotStart() { return timeStart == 0; }函數根據進程的開始時間是否為0判斷本程序是否啟動過。在計算完成時間時,通過timeSever進行判斷。每次時間片執行時都會時timeSever減去相應時間,此處的timeSever是時時更新的剩余服務時間,如果在一個時間片內提前結束了,則完成時間以及本次進程使用的時間都會進行調整,具體實現是通過三元運算符實現timeSever -= timeSlice; timeComplete = timeSever > 0 ? timeNow + timeSlice : timeNow + timeSlice + timeSever; timeUse = timeSever >= 0 ? timeSlice : timeSlice + timeSever;,而也只有在剩余服務時間<=0時即本進程已完成才會進行周轉時間等計算。

RR類進行系統調度時,由主機記錄時間,並按照個一個輪轉片內進程實際使用的時間累加,調用時只需按照到達時間排序一次就好,隨后便是各時間片輪轉,使用一個while (countFinish < num)表示只要有一個進程未完成都會繼續執行循環,而在while循環內部剛好是一個for each循環,各進程按照順序一一輪轉,如果進程未完成,則會調度此進程,完成就countFinish加1。調度時如果是第一次啟動還需賦啟動時間初值,隨后運行本輪次pcb.run(timeNow, timeSlice),記錄下這次實際使用的時間並累加到當前時間上。

測試類Test包含一個主函數用於啟動並時間片長度q,以及一個專門用於接受輸入進程信息的函數。並且輸入的進程數組在測試類中定義,也能實現在RR類中的函數直接更改進程的信息。

流程圖

在這里插入圖片描述

源程序

java

PCB類
import java.text.DecimalFormat;

public class PCB {
    /**
     * 三個公共變量:作業名、到達時間、服務時間
     */
    String threadName;
    int timeArrival;
    int timeSever;

    /**
     * 五個私有變量:計算專用服務時間、開始執行時間、完成時間、周轉時間、帶權周轉時間
     * 一個標志:表示是否還需要調度
     * 一個交互式變量:表示自己本次使用了多少時間
     */
    private int timeSeverFor;
    private int timeStart;
    private int timeComplete;
    private int timeTurnaround;
    private double timeWeightedTurnaround;
    private boolean isFinish = false;
    private int timeUse;

    public PCB() {//允許空參構造器存在
    }

    public PCB(String threadName, int timeArrival, int timeSever) { //正規的有參構造器
        this.threadName = threadName;
        this.timeArrival = timeArrival;
        this.timeSever = timeSever;
        this.timeSeverFor = timeSever;
    }

    public void setTimeStart(int timeStart) {//將由算法調度程序分配開始時間
        this.timeStart = timeStart;
    }

    public boolean isNotStart() {
        return timeStart == 0;
    }

    public int getTimeTurnaround() {
        return timeTurnaround;
    }

    public double getTimeWeightedTurnaround() {
        return timeWeightedTurnaround;
    }

    public boolean isFinish() {
        return isFinish;
    }

    public int getTimeUse() {
        return timeUse;
    }

    public void run(int timeNow, int timeSlice) { //開始調度后的運行內容
        /*計算完成時間*/
        if (timeSever > 0) {
            timeSever -= timeSlice;
            // 此處保證進程在時間片內提前完成的情況下,依然能准確算出完成時間,並返回正確的使用時間
            timeComplete = timeSever > 0 ? timeNow + timeSlice : timeNow + timeSlice + timeSever;
            timeUse = timeSever >= 0 ? timeSlice : timeSlice + timeSever;
        }
        /* 當本次進程完成時,計算周轉時間、帶權周轉時間 */
        if (timeSever <= 0) {
            isFinish = true;
            timeTurnaround = timeComplete - timeArrival;
            DecimalFormat dF = new DecimalFormat("0.00");
            timeWeightedTurnaround = Double.parseDouble(dF.format((double) timeTurnaround / timeSeverFor));
            //調用toString()將內容輸出
            System.out.println(this);
        }
    }

    @Override
    public String toString() {
        return "'" + threadName + '\'' +
                "\t\t" + timeArrival +
                "\t\t" + timeSeverFor +
                "\t\t\t" + timeStart +
                "\t\t" + timeComplete +
                "\t\t" + timeTurnaround +
                "\t\t" + timeWeightedTurnaround;
    }
}
RR類
public class RR {
    public void dispatch(PCB[] pcbarr, int timeSlice) {
        System.out.println("作業名\t到達時間\t服務時間\t開始執行時間\t完成時間\t周轉時間\t帶權周轉時間");
        int num = pcbarr.length;
        //由主機記錄當前時間,以便實現時間片輪轉
        int timeNow = 0;
        sort(pcbarr, num);
        //此后的PCB數組都是依照到達時間排序完成的
        int countFinish = 0;
        while (countFinish < num) {
            countFinish = 0;
            for (PCB pcb : pcbarr) {
                //如果此進程未完成,且時間已到達,則會給該進程一個時間片,否則進行下一個
                if (timeNow >= pcb.timeArrival) {
                    if ((!pcb.isFinish())) {
                        if (pcb.isNotStart()) {
                            pcb.setTimeStart(timeNow);
                        }
                        pcb.run(timeNow, timeSlice);
                        timeNow += pcb.getTimeUse();
                    } else {
                        countFinish++;
                    }
                }else{//若還未到,進行下一輪,沒有需要調度的進程則直接當前時間加一
                    if(pcb.isFinish()){
                    	timeNow++;
                    }
                    break;
                }
            }
        }
        //周轉時間之和與帶權周轉時間之和
        int timeTurnaroundSum = 0;
        double timeWeightedTurnaroundSum = 0;
        for (PCB pcb : pcbarr) {
            timeTurnaroundSum += pcb.getTimeTurnaround();
            timeWeightedTurnaroundSum += pcb.getTimeWeightedTurnaround();
        }
        System.out.println("平均周轉時間:" + (double) timeTurnaroundSum / num +
                ",平均帶權周轉時間:" + timeWeightedTurnaroundSum / num);
    }

    public void sort(PCB[] arr, int num) {
        //根據到達時間對作業進行升序排序,排序方式:選擇排序
        for (int i = 0; i < num - 1; i++) {
            int index = i;
            for (int j = i + 1; j < num; j++) {
                if (arr[j].timeArrival < arr[index].timeArrival) {
                    index = j;
                }
            }
            //將找到的最小值放到第一的位置,進行下一遍循環
            PCB temp = arr[index];
            arr[index] = arr[i];
            arr[i] = temp;
        }
    }
}
Test類
import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        // 設置時間片長度
        System.out.print("時間片輪轉算法\n請設置時間片長度q = ");
        Scanner sc = new Scanner(System.in);
        int timeSlice = sc.nextInt();
        // 讀取輸入的數組
        PCB[] arr1 = dataReadIn();
        //調用時間片輪轉算法
        RR rr = new RR();
        rr.dispatch(arr1, timeSlice);
    }

    public static PCB[] dataReadIn() { //數據讀入函數,直接設為靜態函數,強制要求寫入數據
        System.out.print("請輸入本次需要調度的作業數目:");
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        PCB[] starr = new PCB[n];
        System.out.println("請輸入每一個作業的作業名、到達時間、服務時間(一行一個,中間用空格區分)");
        for (int i = 0; i < n; i++) {
            starr[i] = new PCB(sc.next(), sc.nextInt(), sc.nextInt());
        }
        return starr;
    }
}

運行時的初值和結果

時間片輪轉算法
請設置時間片長度q = 1
請輸入本次需要調度的作業數目:5
請輸入每一個作業的作業名、到達時間、服務時間(一行一個,中間用空格區分)
A 0 4
B 1 3
C 2 4
D 3 2
E 4 4
作業名 到達時間 服務時間 開始執行時間 完成時間 周轉時間 帶權周轉時間
'D' 3 2 3 9 6 3.0
'B' 1 3 1 12 11 3.67
'A' 0 4 5 15 15 3.75
'C' 2 4 2 16 14 3.5
'E' 4 4 4 17 13 3.25
平均周轉時間:11.8,平均帶權周轉時間:3.434

時間片輪轉算法
請設置時間片長度q = 4
請輸入本次需要調度的作業數目:5
請輸入每一個作業的作業名、到達時間、服務時間(一行一個,中間用空格區分)
A 0 4
B 1 3
C 2 4
D 3 2
E 4 4
作業名 到達時間 服務時間 開始執行時間 完成時間 周轉時間 帶權周轉時間
'A' 0 4 0 4 4 1.0
'B' 1 3 4 7 6 2.0
'C' 2 4 7 11 9 2.25
'D' 3 2 11 13 10 5.0
'E' 4 4 13 17 13 3.25
平均周轉時間:8.4,平均帶權周轉時間:2.7

與理想狀態相同
image-20211118235513791image-20211118235548720


在這里插入圖片描述

在這里插入圖片描述

python

"""設計時間片輪轉算法來實現調度"""
import copy
from queue import Queue

count = int(input('請輸入進程數目:'))
process = []


# 輸入進程相關信息
def inputprocess():
    i = 0
    while i < count:
        print('-------------------')
        process_name = input('請輸入第%d個進程名:' % (i + 1))
        arrive_time = float(input('請輸入達到時間:'))
        service_time = float(input('請輸入服務時間:'))
        priority = int(input('請輸入優先數:'))
        process.append([process_name, arrive_time, service_time, priority, 0, 0, 0])
        # 后面3個0分別表示完成、周轉、帶權周轉時間
        i += 1


# 時間片輪轉調度算法
def RRS(rr):
    RPro = process[:]
    RPro.sort(key=lambda item: item[1])  # 按照達到時間從小到大排序
    temppro = copy.deepcopy(RPro)
    qu = Queue()
    nowP = temppro[0]
    if nowP[2] > rr:  # 服務時間大於時間片
        nowP[2] -= rr  # 還需要服務的時間
        nowtime = nowP[1] + rr  # 當前完成時間
    else:  # 服務時間小於等於時間片
        nowP[4] = nowP[1] + nowP[2]  # 完成時間
        nowP[5] = nowP[4] - nowP[1]
        nowP[6] = nowP[5] / nowP[2]
        nowtime = nowP[1] + nowP[2]  # 當前完成時間
        nowP[2] = 0  # 服務結束
    if nowP[2] > 0:  # 服務未結束,放到隊尾
        qu.put(nowP)
    i = 0
    flag = 1
    while flag:
        if i >= count - 1:  # 所有進程均已達到
            nowP = qu.get()
        else:
            if temppro[i + 1][1] <= nowtime:  # 下一個進程已經到達
                nowP = temppro[i + 1]  # 調度最新到來的進程
                i += 1
            else:  # 下一個進程還未到達
                if not qu.empty():  # 隊列非空
                    nowP = qu.get()  # 調度當前隊頭進程
                else:  # 隊列已空
                    nowP = temppro[i + 1]
                    nowtime = nowP[1]
                    i += 1
        if nowP[2] > rr:  # 服務時間大於時間片
            nowP[2] -= rr  # 還需要服務的時間
            nowtime = nowtime + rr  # 當前完成時間
        else:  # 服務時間小於等於時間片
            ind = temppro.index(nowP)  # 獲得該進程的索引
            servicetime = RPro[ind][2]  # 原始的服務時間
            nowP[4] = nowtime + nowP[2]  # 完成時間
            nowP[5] = nowP[4] - nowP[1]
            nowP[6] = nowP[5] / servicetime
            nowtime = nowP[4]  # 更新當前完成時間
            nowP[2] = 0  # 服務結束
        if nowP[2] > 0:  # 服務未結束,放到隊尾
            qu.put(nowP)
        for j in range(count):
            if temppro[j][2] == 0:
                flag = 0
            else:
                flag = 1  # 還有未服務結束的進程
                break
    for i in range(count):
        RPro[i][4] = temppro[i][4]
        RPro[i][5] = temppro[i][5]
        RPro[i][6] = temppro[i][6]
    aver_TAT = 0
    aver_WTAT = 0
    for i in range(count):
        aver_TAT += RPro[i][5]
        aver_WTAT += RPro[i][6]
    aver_TAT /= count  # 平均周轉時間
    aver_WTAT /= count  # 平均帶權周轉時間
    # 輸出
    RPro.sort(key=lambda item: (item[1]))  # 按照到達時間時間輸出
    print('時間片輪轉調度算法計算結果:')
    for pro in RPro:
        print('{0[0]}進程在時刻{0[1]}到來,服務時間為{0[2]},優先級為{0[3]},完成時間為{0[4]},周轉時間為{0[5]},帶權周轉時間為{0[6]}'.format(pro))
    print('本次調度的平均周轉時間為{0},平均帶權周轉時間為{1}'.format(aver_TAT, aver_WTAT))


if __name__ == '__main__':
    inputprocess()
    print('-------------------')
    rr = int(input('下面將使用時間片輪轉調度算法,請輸入時間片大小:'))
    RRS(rr)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM