面试题答案
一键面试设计思路
- 资源管理:使用信号量来表示系统中可用的资源数量。可以借助
golang.org/x/sync/semaphore
包,该包提供了一个简单的信号量实现。 - 任务优先级:为每个任务定义一个优先级字段。优先级可以用整数表示,数字越大优先级越高。
- 任务队列:使用一个优先级队列来存储等待资源的任务。优先级高的任务先获取资源。
核心代码实现
package main
import (
"container/heap"
"fmt"
"golang.org/x/sync/semaphore"
"sync"
)
// Task 定义任务结构
type Task struct {
id int
priority int
// 这里假设任务需要的资源数量固定为1,实际可按需调整
resourceNeeded int
}
// PriorityQueue 定义优先级队列
type PriorityQueue []*Task
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool {
// 这里按照优先级从高到低排序
return pq[i].priority > pq[j].priority
}
func (pq PriorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
}
func (pq *PriorityQueue) Push(x interface{}) {
*pq = append(*pq, x.(*Task))
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n - 1]
*pq = old[0 : n - 1]
return item
}
func main() {
var wg sync.WaitGroup
// 假设系统有10个资源
sem := semaphore.NewWeighted(10)
taskQueue := &PriorityQueue{}
heap.Init(taskQueue)
// 模拟添加任务
tasks := []Task{
{id: 1, priority: 3, resourceNeeded: 1},
{id: 2, priority: 1, resourceNeeded: 1},
{id: 3, priority: 2, resourceNeeded: 1},
}
for _, task := range tasks {
heap.Push(taskQueue, &task)
}
for taskQueue.Len() > 0 {
task := heap.Pop(taskQueue).(*Task)
wg.Add(1)
go func(t *Task) {
defer wg.Done()
// 获取资源
if err := sem.Acquire(nil, t.resourceNeeded); err != nil {
fmt.Printf("Task %d failed to acquire resource: %v\n", t.id, err)
return
}
defer sem.Release(t.resourceNeeded)
fmt.Printf("Task %d with priority %d is running\n", t.id, t.priority)
// 模拟任务执行
}(task)
}
wg.Wait()
}
在这段代码中:
Task
结构体定义了任务的属性,包括任务ID、优先级和所需资源数量。PriorityQueue
实现了heap.Interface
接口,用于实现优先级队列。- 在
main
函数中,初始化了信号量和任务队列,并将任务添加到队列中。 - 通过
go
协程并发执行任务,每个任务在执行前获取资源,执行完毕后释放资源,确保资源竞争不会发生。