用go实现协程:有2万个任务,同一时刻1000个任务并发,等待所有任务完成后退出

277 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

用go语言实现协程代码:总共有2万个任务,但同时只能有1000个任务并行,等待所有协程任务完成后退出程序。

package main

import (
	"fmt"
	"sync"
)
const (
	taskCount = 20000
	concurrentTaskCount = 1000
)

func main() {
	var wg sync.WaitGroup
	wg.Add(taskCount)

	tasks := make(chan struct{}, concurrentTaskCount)

	for i := 0; i < taskCount; i++ {
		tasks <- struct{}{}
		go func(taskNum int) {
			defer func() {
				<-tasks
				wg.Done()
			}()

			// Do the task here
			fmt.Printf("Task %d started\n", taskNum)
			// ...
			fmt.Printf("Task %d finished\n", taskNum)
		}(i)
	}

	wg.Wait()
}

代码解释: 该代码实现了 2 万个任务,但同时只能有 1000 个任务并行的协程代码。使用了 Go 内置的 sync.WaitGroup 来等待所有任务完成后再退出程序。同时使用了一个带缓冲的通道 tasks,限制同时并行的任务数量,保证每次只有 1000 个任务并行执行。

关键代码解答

(1)上面的 <-tasks 是什么意思

"<-tasks" 是 Go 语言中的一个 channel 操作,它的意思是从 "tasks" 这个 channel 中读取一个数据。在 Go 语言中,channel 是一种特殊的数据结构,用来在协程间进行数据交换。读取 channel 的操作类似于读取一个数组中的数据,只不过在 channel 中读取的数据需要通过阻塞等待方式读取。

(2)上面的tasks <- struct{}{} 是什么意思

`"tasks <- struct{}{}" 是 Go 语言中的通道语法,意思是将空结构体 struct{}{} 发送到通道 tasks。通道是 Go 语言的一种用于实现协程间通信的数据结构,支持在不同协程间传递数据。

在这个代码中,通道 tasks 被用作信号,用于记录已完成的任务数量,其作用是限制同时运行的协程数量,并在所有协程完成后通知主程序退出。`