面试题答案
一键面试通道容量设置原则
- 高并发且任务处理时间短:如果系统并发量高,但每个任务处理时间很短,通道容量可以适当设置得大一些。这样可以在一定程度上缓冲任务,减少因通道满而导致的阻塞,提高整体的并发处理能力。
- 高并发且任务处理时间长:当并发量高且任务处理时间长时,过大的通道容量可能会导致大量任务堆积在通道中,占用过多内存。此时通道容量应根据系统资源(如内存)以及期望的任务处理速度来设置,避免内存溢出等问题。可以考虑设置较小的通道容量,并结合其他机制(如任务队列限流等)来控制任务的流入。
Go代码示例
package main
import (
"fmt"
"sync"
)
// Task 定义任务结构体
type Task struct {
ID int
}
// ProcessTask 模拟任务处理函数
func ProcessTask(task Task) int {
// 模拟任务处理时间
// 这里简单返回任务ID
return task.ID
}
func main() {
const (
numTasks = 100
concurrency = 10
// 根据任务处理时间和并发量设置通道容量
// 这里假设任务处理时间较短,设置一个相对较大的通道容量
channelCapacity = 50
)
var wg sync.WaitGroup
taskCh := make(chan Task, channelCapacity)
resultCh := make(chan int)
// 启动工作协程
for i := 0; i < concurrency; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for task := range taskCh {
result := ProcessTask(task)
resultCh <- result
}
}()
}
// 提交任务
for i := 0; i < numTasks; i++ {
task := Task{ID: i}
taskCh <- task
}
close(taskCh)
// 收集结果
go func() {
wg.Wait()
close(resultCh)
}()
for result := range resultCh {
fmt.Printf("Task %d processed, result: %d\n", result, result)
}
}
在上述代码中:
- 任务结构体
Task
:定义了任务的基本结构,这里简单包含一个任务ID。 ProcessTask
函数:模拟任务处理过程,返回任务ID作为处理结果。- 主函数
main
:- 定义了任务数量
numTasks
、并发数concurrency
和通道容量channelCapacity
。 - 创建了任务通道
taskCh
和结果通道resultCh
。 - 启动了多个工作协程,从任务通道
taskCh
中获取任务并处理,将结果发送到结果通道resultCh
。 - 向任务通道
taskCh
中提交任务,完成后关闭任务通道。 - 通过
WaitGroup
等待所有工作协程完成任务处理,然后关闭结果通道,最后从结果通道中收集并打印任务处理结果。
- 定义了任务数量