面试题答案
一键面试关键数据结构
- 任务结构体:
type Task struct {
ID int
Priority int
// 其他任务相关数据
Func func()
}
- 优先级队列:用于存储任务,可使用堆(heap)数据结构实现。Go标准库中的
container/heap
包可帮助实现堆。
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 EnqueueTask(task *Task, pq *PriorityQueue) {
heap.Init(pq)
heap.Push(pq, task)
}
- 任务出队执行:调度器从优先级队列中取出优先级最高的任务(堆顶元素),并执行该任务的函数。
func DequeueAndExecute(pq *PriorityQueue) {
heap.Init(pq)
for pq.Len() > 0 {
task := heap.Pop(pq).(*Task)
task.Func()
}
}
- 结合Go调度器:在Go调度器的基础上,可以创建一个或多个goroutine来执行任务出队和执行的操作。例如:
func main() {
var pq PriorityQueue
// 模拟添加任务
task1 := &Task{ID: 1, Priority: 5, Func: func() { println("Task 1 executed") }}
task2 := &Task{ID: 2, Priority: 3, Func: func() { println("Task 2 executed") }}
EnqueueTask(task1, &pq)
EnqueueTask(task2, &pq)
go DequeueAndExecute(&pq)
// 防止主程序退出
select {}
}
在实际应用中,可能还需要考虑任务阻塞、资源限制等更多因素,确保高优先级任务在合适的时机能够真正优先执行。