0%

go-异步等待操作,和python有一丢丢相似

go-异步等待操作,和python有一丢丢相似

为了限制并发执行的goroutines数量,您可以使用一个带缓冲的通道作为信号量(semaphore)。信号量通道中的元素数量表示当前可以运行的并发任务数。通过向该通道发送和接收空结构体 struct{},您可以控制同时运行的任务数量。

以下是如何修改您的代码以限制最大并发数为3的示例:

package main  

import (
"fmt"
"time"
)

func asyncOperation(resultChan chan<- string, id int, sem chan struct{}) {
// 获取一个信号量,表示开始一个任务
sem <- struct{}{}

defer func() {
<-sem // 任务结束时释放信号量
}()

// 模拟异步操作,比如网络请求或数据处理
fmt.Println("进来执行任务了", id)
time.Sleep(2 * time.Second) // 假设操作需要2秒钟
result := fmt.Sprintf("异步操作结果 %d", id)
resultChan <- result // 将结果发送到channel
}

func main() {
const numOperations = 20
results := make([]string, numOperations)
resultChan := make(chan string) // 创建一个用于接收结果的channel
sem := make(chan struct{}, 3) // 创建一个信号量通道,最大并发数为3

// 启动所有异步操作goroutines
for i := 0; i < numOperations; i++ {
go asyncOperation(resultChan, i+1, sem)
}

// 收集所有异步操作的结果
for i := 0; i < numOperations; i++ {
// 从channel接收结果,这会阻塞直到结果可用
results[i] = <-resultChan
fmt.Println("异步操作完成:", results[i])
}

// 所有结果都收集完毕后,可以继续后续处理
fmt.Println("所有异步操作已完成。")
}

在这个修改后的代码中,我添加了一个名为 sem 的信号量通道,其缓冲大小为3,表示最多允许3个goroutines同时运行。在 asyncOperation 函数中,每个goroutine在开始执行任务前会先向 sem 通道发送一个空结构体,以获取一个信号量。任务完成后,它会从 sem 通道中接收一个空结构体来释放信号量,从而允许其他等待的goroutines开始执行。

这样,您就可以确保在任何时候最多只有3个goroutines在并发执行,从而避免过度消耗系统资源。

执行结果:

/usr/local/go/bin/go build -o /private/var/folders/dq/j9svchmn5hdcpr4r4yckxhjr0000gn/T/GoLand/___go_build_test_02_go /code/GolandProjects/test/test_02.go #gosetup
/private/var/folders/dq/j9svchmn5hdcpr4r4yckxhjr0000gn/T/GoLand/___go_build_test_02_go
进来执行任务了 13
进来执行任务了 3
进来执行任务了 2
进来执行任务了 20
进来执行任务了 1
进来执行任务了 11
进来执行任务了 12
进来执行任务了 4
异步操作完成: 异步操作结果 3
异步操作完成: 异步操作结果 12
异步操作完成: 异步操作结果 1
异步操作完成: 异步操作结果 20
异步操作完成: 异步操作结果 11
异步操作完成: 异步操作结果 2
异步操作完成: 异步操作结果 13
进来执行任务了 5
进来执行任务了 7
进来执行任务了 10
进来执行任务了 8
进来执行任务了 9
进来执行任务了 6
进来执行任务了 17
异步操作完成: 异步操作结果 6
异步操作完成: 异步操作结果 10
异步操作完成: 异步操作结果 8
异步操作完成: 异步操作结果 9
异步操作完成: 异步操作结果 4
异步操作完成: 异步操作结果 5
异步操作完成: 异步操作结果 7
进来执行任务了 14
进来执行任务了 16
进来执行任务了 15
进来执行任务了 19
进来执行任务了 18
异步操作完成: 异步操作结果 17
异步操作完成: 异步操作结果 18
异步操作完成: 异步操作结果 16
异步操作完成: 异步操作结果 15
异步操作完成: 异步操作结果 19
异步操作完成: 异步操作结果 14
所有异步操作已完成。

进程 已完成,退出代码为 0