golang模擬動態高優先權優先調度算法


實驗二  動態高優先權優先調度

實驗內容

模擬實現動態高優先權優先(若數值越大優先權越高,每運行一個時間單位優先權-n,若數值越小優先權越高,沒運行一個時間單位優先權+n),具體如下:

設置進程體:進程名,進程的到達時間,服務時間,初始優先權,進程狀態(W——等待,R——運行,F——完成),進程間的鏈接指針

進程初始化:由用戶輸入進程名、服務時間、初始優先權進行初始化,同時,初始化進程的狀態為W。

顯示函數:在進程調度前、調度中和調度后進行顯示。

排序函數:對就緒狀態的進程按照優先權排序。優先權相同時進入等待隊列時間早的進程在前。注意考慮到達時間

調度函數:每次從等待隊列隊首調度優先權最高的進程執行,狀態變化。並在執行一個時間單位后優先權變化,服務時間變化,狀態變化。當服務時間為0時,狀態變為F。

刪除函數:撤銷狀態為F的進程。

實驗要求

1、  測試數據可以隨即輸入或從文件中讀入。

2、  必須要考慮到進程的到達時間

3、  最終能夠計算每一個進程的周轉時間。

 

實驗代碼

1.txt

process1 1 5 2 W
process2 1 4 7 W
process3 1 8 3 W
process5 1 6 9 W
process4 1 15 6 W

 

main.go

package main

import (
    "bufio"
    "container/heap"
    "fmt"
    "os"
    "strconv"
    "strings"
    "time"
)

type Item struct {
    name       string
    priority   int
    index      int
    arrival    int
    service    int
    oldservice int
    state      string
}

type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {

    if pq[i].priority == pq[j].priority {
        return pq[i].service < pq[i].service
    }
    return pq[i].priority > pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].index = i
    pq[j].index = j
}

func (pq *PriorityQueue) Push(x interface{}) {
    n := len(*pq)
    item := x.(*Item)
    item.index = n
    *pq = append(*pq, item)
}

//優先隊列的Pop並不是用這個Pop,最后的元素並不是優先級最高的!
func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    item.index = -1
    *pq = old[0 : n-1]
    return item
}

func (pq *PriorityQueue) Top() *Item {
    item := heap.Pop(pq).(*Item)
    heap.Push(pq, item)
    return item
}

func (pq *PriorityQueue) update(item *Item, priority, service int, state string) {
    item.priority = priority
    item.service = service
    item.state = state
    heap.Fix(pq, item.index)
}

//創建優先隊列
var pq = make(PriorityQueue, 0)

func main() {
    f, err := os.OpenFile("1.txt", os.O_RDONLY, 0777)
    if err != nil {
        fmt.Println("沒有找到1.txt!")
        os.Exit(1)
    }
    fmt.Println("請輸入每秒改變優先級n")
    n := 1
    fmt.Scan(&n)
    reader := bufio.NewReader(f)

    for i := 0; i < 5; i++ {
        //每次讀取一行
        buf, _, _ := reader.ReadLine()
        sli := strings.Fields(string(buf))
        priint, _ := strconv.Atoi(sli[3])
        arrint, _ := strconv.Atoi(sli[1])
        serint, _ := strconv.Atoi(sli[2])
        //創建實例
        one := &Item{
            name:       sli[0],
            priority:   priint,
            index:      i,
            arrival:    arrint,
            service:    serint,
            oldservice: serint,
            state:      sli[4],
        }
        heap.Push(&pq, one)
    }
    //初始化堆
    heap.Init(&pq)
    fmt.Println("請輸入第x秒后的狀態:")
    x := 0
    fmt.Scan(&x)
    //執行, 初始總數n為5,x為循環次數

    num := 5
    for second := 1; second <= x; second++ {

        time.Sleep(time.Second)
        // pq[num] != heap.Pop(*pq)!!!

        //臨時優先隊列
        var tempq = make(PriorityQueue, 0)

        //遍歷所有堆元素,僅pq[0]優先級最高!
        for i := 0; i < num; i++ {
            onepq := pq[i]

            if onepq.state == "F" {
                //添加到tempq
                tempq = append(tempq, onepq)
                continue
            }

            //服務時間不為0,就讓其-1,state設為R
            if onepq.service != 0 {
                if i == 0 {
                    //優先級最高
                    onepq.priority = pq[i].priority - n
                    onepq.service = pq[i].service - 1
                    onepq.state = "R"
                } else {
                    //堆里其他元素
                    onepq.priority = pq[i].priority + n
                    onepq.state = "W"
                }
            } else {
                //service=0, state設為F
                onepq.state = "F"
            }

            //添加到tempq
            tempq = append(tempq, onepq)
        }

        //刪除堆里所有元素
        for pq.Len() > 0 {
            heap.Pop(&pq)
        }

        //把所有元素加到堆里
        for _, v := range tempq {
            heap.Push(&pq, v)
        }

        //輸出
        fmt.Printf("\n第%d秒的狀態表示\n", second)
        fmt.Println("進程名  |  服務時間  |  目前優先級  |  進程狀態  |  平均周轉時間")

        //輸出堆
        for i := 0; i < num; i++ {
            if pq[i].oldservice == pq[i].service {
                fmt.Printf("%v      %v            %v            %v              0\n", pq[i].name, pq[i].service, pq[i].priority, pq[i].state)
            } else {
                fmt.Printf("%v      %v            %v            %v              %v\n", pq[i].name, pq[i].service, pq[i].priority, pq[i].state, (second-pq[i].arrival)*1.0/(pq[i].oldservice-pq[i].service))
            }

        }
    }
}

/*
    使用了golang的container/heap包,需要手動實現less/len/swap/push/pop方法,這里也自定義了update和top方法,需要注意有以下幾點:
    1. heap並不是按優先級排序的,所以不能用for遍歷,僅pq[0]優先級最高
    2. 在遍歷堆內所有節點時不能直接update,因為fix方法會重新構建堆,我這里使用的方式是用切片來保存堆中所有的元素,空堆后再一次性push
*/

 

 

實驗截圖

前4秒狀態:

 

 

后2秒狀態:

 


免責聲明!

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



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