MST

星途 面试题库

面试题:针对特定场景对Go WaitGroup进行定制化并发控制精度优化

假设存在一个场景:有一组任务,每个任务的执行时间有较大差异,且整体任务数量在动态变化。请你设计一种基于WaitGroup的并发控制精度优化方案,既要保证整体任务高效执行,又要避免资源过度占用,并详细说明设计思路及关键代码实现。
28.6万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 任务分块:由于任务执行时间差异大且数量动态变化,将任务按照一定规则分成多个小块,这样可以更细粒度地控制并发。例如,可以根据任务的预计执行时间或其他属性进行分块。
  2. 动态调整并发数:使用一个控制变量来动态调整同时执行的任务数量。根据系统资源状况(如CPU使用率、内存占用等)或者已完成任务的反馈来调整这个并发数。
  3. WaitGroup使用:为每个任务块创建一个WaitGroup,当任务块中的所有任务完成时,通过WaitGroup来通知主线程。这样主线程无需等待所有任务全部完成,而是可以分块等待,提高并发控制精度。

关键代码实现(以Go语言为例)

package main

import (
    "fmt"
    "sync"
    "time"
)

func task(id int, duration time.Duration, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Task %d started\n", id)
    time.Sleep(duration)
    fmt.Printf("Task %d finished\n", id)
}

func main() {
    // 模拟动态变化的任务列表
    tasks := []struct {
        id       int
        duration time.Duration
    }{
        {1, 2 * time.Second},
        {2, 5 * time.Second},
        {3, 1 * time.Second},
        {4, 3 * time.Second},
    }

    maxConcurrent := 2 // 初始最大并发数
    var wg sync.WaitGroup
    taskCh := make(chan struct{}, maxConcurrent)

    for _, t := range tasks {
        taskCh <- struct{}{}
        wg.Add(1)
        go func(id int, duration time.Duration) {
            defer func() { <-taskCh }()
            task(id, duration, &wg)
        }(t.id, t.duration)
    }

    wg.Wait()
    close(taskCh)
    fmt.Println("All tasks completed")
}
  1. task函数:每个任务的具体执行逻辑,执行完成后调用wg.Done()通知WaitGroup。
  2. main函数
    • 定义任务列表。
    • 设置初始最大并发数maxConcurrent,并使用一个带缓冲的通道taskCh来控制并发数量。
    • 遍历任务列表,向通道taskCh发送信号以获取执行权,增加WaitGroup计数,然后启动协程执行任务。任务执行完后从通道中取出信号,释放执行权。
    • 最后调用wg.Wait()等待所有任务完成,并关闭通道。

通过这种方式,可以在保证任务高效执行的同时,避免资源过度占用,实现基于WaitGroup的并发控制精度优化。