zoukankan      html  css  js  c++  java
  • 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("
    第%d秒的状态表示
    ", second)
            fmt.Println("进程名  |  服务时间  |  目前优先级  |  进程状态  |  平均周转时间")
    
            //输出堆
            for i := 0; i < num; i++ {
                if pq[i].oldservice == pq[i].service {
                    fmt.Printf("%v      %v            %v            %v              0
    ", pq[i].name, pq[i].service, pq[i].priority, pq[i].state)
                } else {
                    fmt.Printf("%v      %v            %v            %v              %v
    ", 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秒状态:

     

  • 相关阅读:
    MySQL的count函数注意点
    case when语句的报错问题
    redis的主从搭建与sentinel高可用服务的搭建
    解析范式(1NF-4NF)
    对SQL语言的相关学习
    ASP.NET Core MVC+EF Core项目实战
    ASP.NET Core +Highchart+ajax绘制动态柱状图
    tab页卡效果!
    今天我注册了迅雷快传
    触发器学习笔记(:new,:old用法)
  • 原文地址:https://www.cnblogs.com/lesroad/p/10704040.html
Copyright © 2011-2022 走看看