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秒状态:

 

posted @ 2019-04-14 09:54  LesRoad  阅读(1779)  评论(0编辑  收藏  举报