面试题答案
一键面试实现思路
- 创建任务队列:使用 Go 语言的 channel 作为任务队列,用于存储待处理的任务。
- 创建 worker 池:根据设定的固定 worker 数量,启动相应数量的 goroutine 作为 worker,每个 worker 从任务队列中取出任务并处理。
- 任务分发:将任务发送到任务队列中,由 worker 自动从队列中获取任务,实现简单的负载均衡,即哪个 worker 空闲,就从队列中取出任务进行处理。
- 关闭机制:提供一种机制来关闭任务队列和 worker,确保程序能优雅退出。
核心代码示例
package main
import (
"fmt"
"sync"
)
// Task 定义任务结构
type Task struct {
ID int
// 可根据实际需求添加更多任务相关字段
}
// Worker 定义 worker 结构
type Worker struct {
ID int
wg *sync.WaitGroup
}
// 处理任务的函数
func (w *Worker) processTask(task Task) {
fmt.Printf("Worker %d is processing task %d\n", w.ID, task.ID)
// 实际任务处理逻辑,这里用打印模拟
}
// 启动 worker
func (w *Worker) start(taskQueue chan Task) {
defer w.wg.Done()
for task := range taskQueue {
w.processTask(task)
}
}
func main() {
const workerCount = 3
const taskCount = 10
var wg sync.WaitGroup
taskQueue := make(chan Task)
// 创建 worker 池
for i := 0; i < workerCount; i++ {
worker := Worker{
ID: i + 1,
wg: &wg,
}
wg.Add(1)
go worker.start(taskQueue)
}
// 分发任务
for i := 0; i < taskCount; i++ {
task := Task{ID: i + 1}
taskQueue <- task
}
// 关闭任务队列,通知 worker 停止
close(taskQueue)
// 等待所有 worker 完成任务
wg.Wait()
}
任务分发逻辑
在 main
函数中,通过 for
循环将任务发送到 taskQueue
中。只要 taskQueue
有空间(没有满),任务就可以发送进去,而不用关心哪个 worker 会处理这个任务。
worker 的工作流程
- 每个 worker 启动一个 goroutine,调用
start
方法。 start
方法通过for... range
从taskQueue
中接收任务。- 接收到任务后,调用
processTask
方法处理任务。 - 当
taskQueue
关闭时,for... range
循环结束,worker 的 goroutine 也随之结束。