面试题答案
一键面试设计思路
- 任务表示:使用结构体来表示每个任务,结构体中包含任务的执行函数、依赖任务的ID列表、任务执行结果的存储字段。
- 依赖管理:构建一个依赖关系图,通过任务ID来表示任务间的依赖。使用一个队列来存储没有依赖或依赖已满足的任务,逐步执行这些任务。
- 并发执行:利用Go的goroutine来并发执行任务。使用通道(channel)来传递任务的执行结果。
- 结果汇总:在所有任务执行完毕后,汇总每个任务的多值返回结果。
关键代码示例
package main
import (
"fmt"
"sync"
)
// Task 表示一个任务
type Task struct {
ID int
Execute func() (interface{}, int, int) // 返回执行结果、执行时间、资源消耗
DependsOn []int
Result interface{}
Time int
Resource int
}
// TaskManager 管理任务的执行
type TaskManager struct {
Tasks map[int]*Task
WaitGroup sync.WaitGroup
}
// NewTaskManager 创建一个新的任务管理器
func NewTaskManager() *TaskManager {
return &TaskManager{
Tasks: make(map[int]*Task),
}
}
// AddTask 添加一个任务
func (tm *TaskManager) AddTask(task *Task) {
tm.Tasks[task.ID] = task
}
// ExecuteTasks 执行所有任务
func (tm *TaskManager) ExecuteTasks() {
var readyQueue []*Task
for _, task := range tm.Tasks {
if len(task.DependsOn) == 0 {
readyQueue = append(readyQueue, task)
}
}
resultCh := make(chan *Task)
defer close(resultCh)
for len(readyQueue) > 0 {
task := readyQueue[0]
readyQueue = readyQueue[1:]
tm.WaitGroup.Add(1)
go func(t *Task) {
defer tm.WaitGroup.Done()
result, time, resource := t.Execute()
t.Result = result
t.Time = time
t.Resource = resource
resultCh <- t
}(task)
for _, newTask := range tm.Tasks {
if contains(newTask.DependsOn, task.ID) {
allDependsMet := true
for _, depID := range newTask.DependsOn {
if tm.Tasks[depID].Result == nil {
allDependsMet = false
break
}
}
if allDependsMet {
readyQueue = append(readyQueue, newTask)
}
}
}
}
go func() {
tm.WaitGroup.Wait()
close(resultCh)
}()
for result := range resultCh {
fmt.Printf("Task %d executed. Result: %v, Time: %d, Resource: %d\n", result.ID, result.Result, result.Time, result.Resource)
}
}
func contains(slice []int, item int) bool {
for _, a := range slice {
if a == item {
return true
}
}
return false
}
// 示例任务执行函数
func exampleExecute() (interface{}, int, int) {
// 模拟任务执行
return "Task result", 10, 50
}
func main() {
tm := NewTaskManager()
task1 := &Task{
ID: 1,
Execute: exampleExecute,
DependsOn: []int{},
}
task2 := &Task{
ID: 2,
Execute: exampleExecute,
DependsOn: []int{1},
}
tm.AddTask(task1)
tm.AddTask(task2)
tm.ExecuteTasks()
}
上述代码实现了一个简单的任务管理器,它能够处理任务间的依赖关系并并发执行任务,最后汇总每个任务的多值返回结果。在实际应用中,可根据具体需求进一步扩展和优化,例如任务执行函数的参数化、任务优先级处理等。