go 利用channel控制并发

任务数量为50,并发在5,全部都要执行

Go 复制代码
package main

import (
	"fmt"
	"time"
)

type Con struct {
	num  int
	time string
}

func main() {

		//channel实现并发控制
	// 定义同时执行的任务数量
	concurrencyLevel := 5
	//总任务数
	totalTask := 50

	// 创建一个有缓冲的 channel 用于控制并发数
	taskChan := make(chan int, concurrencyLevel)

	// 创建一个 channel 用于标记所有任务完成
	doneChan := make(chan *Con, totalTask)

	// 启动指定数量的 goroutine 来并发执行任务
	for i := 0; i < concurrencyLevel; i++ {
		go concurrentTask(taskChan, doneChan)
	}

	// 发送任务到 taskChan

	//循环发送任务,保证每个任务都能发送到,如果发送任务时 taskChan 阻塞,等待一段时间再重试
	for i := 1; i <= totalTask; i++ {
		select {
		// 发送任务到 taskChan
		case taskChan <- i:
			//fmt.Printf("任务 %d 已发送\n", i)
		default:
			fmt.Println("任务发送阻塞,等待空闲...", i)
			// 等待 1 秒钟再重试
			time.Sleep(1 * time.Second)
			i--
		}
	}

	// 关闭 taskChan,通知所有的 goroutine 没有更多的任务
	close(taskChan)

	// 关闭 doneChan
	close(doneChan)

	 等待所有任务完成,并关闭 doneChan
	for res := range doneChan {
		fmt.Printf("任务 %d 完成, 完成时间:%s\n", res.num, res.time)
	}

	fmt.Println("所有任务已完成")

}


// 模拟一个并发执行的任务
func concurrentTask(taskChan chan int, doneChan chan *Con) {
	defer func() {
		// 捕获 panic,recover() 函数可以让程序从 panic 中恢复
		if r := recover(); r != nil {
			fmt.Println("任务发生panic,正在恢复:", r)
		}
	}()

	// 从 taskChan 中获取任务
	for task := range taskChan {
		fmt.Printf("处理任务 %d\n", task)
		time.Sleep(1 * time.Second) // 模拟任务执行时间
		//任务执行完毕,将任务结果发送到 doneChan
		doneChan <- &Con{num: task, time: time.Now().Format("2006-01-02 15:04:05")}
	}

}

任务数量为50,并发在5,遇到阻塞的就不再执行

Go 复制代码
package main

import (
	"fmt"
	"time"
)

type Con struct {
	num  int
	time string
}

func main() {

//channel实现并发控制
	// 定义同时执行的任务数量
	concurrencyLevel := 5
	//总任务数
	totalTask := 50

	// 创建一个有缓冲的 channel 用于控制并发数
	taskChan := make(chan int, concurrencyLevel)

	// 创建一个 channel 用于标记所有任务完成
	doneChan := make(chan *Con, totalTask)

	// 启动指定数量的 goroutine 来并发执行任务
	for i := 0; i < concurrencyLevel; i++ {
		go concurrentTask(taskChan, doneChan)
	}

	// 发送任务到 taskChan

	//循环发送任务,保证每个任务都能发送到,如果发送任务时 taskChan 阻塞,等待一段时间再重试
	for i := 1; i <= totalTask; i++ {
		select {
		// 发送任务到 taskChan
		case taskChan <- i:
			//fmt.Printf("任务 %d 已发送\n", i)
		default:
			fmt.Println("任务发送阻塞,等待空闲...", i)
		}
	}

	// 关闭 taskChan,通知所有的 goroutine 没有更多的任务
	close(taskChan)

	// 关闭 doneChan
	close(doneChan)

	 等待所有任务完成,并关闭 doneChan
	for res := range doneChan {
		fmt.Printf("任务 %d 完成, 完成时间:%s\n", res.num, res.time)
	}

	fmt.Println("所有任务已完成")

}

// 模拟一个并发执行的任务
func concurrentTask(taskChan chan int, doneChan chan *Con) {
	defer func() {
		// 捕获 panic,recover() 函数可以让程序从 panic 中恢复
		if r := recover(); r != nil {
			fmt.Println("任务发生panic,正在恢复:", r)
		}
	}()

	// 从 taskChan 中获取任务
	for task := range taskChan {
		fmt.Printf("处理任务 %d\n", task)
		time.Sleep(1 * time.Second) // 模拟任务执行时间
		//任务执行完毕,将任务结果发送到 doneChan
		doneChan <- &Con{num: task, time: time.Now().Format("2006-01-02 15:04:05")}
	}

}
相关推荐
Raas10018 分钟前
AI网关和OpenRouter区别?MAI Gateway(魔芋企业级AI网关)企业级方案对比指南
大数据·开发语言·人工智能·gateway·php·ai网关·mai gateway
点心的游戏开发世界8 小时前
GDScript 入门笔记(十一):Lambda 与匿名函数
开发语言·笔记·游戏引擎·godot
摇滚侠8 小时前
《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 使用 JdbcTemplate 阅读笔记 32
spring boot·笔记·后端
步行cgn9 小时前
@Configuration 详解:Spring 配置类的核心注解
java·后端·spring
事圆则缓10 小时前
Kotlin 协程完全指南
开发语言·kotlin
我爱写代码i10 小时前
BeLink - 支持生成多种URL 缩短网址PHP源码
开发语言·php·短网址php源码
Java后端的Ai之路10 小时前
20、Python - 备忘录模式
开发语言·人工智能·python·外观模式·备忘录模式
桦说编程11 小时前
【AtomicAgent系列1】变异测试——过去做不起,现在 agent 做得起
后端·ai编程·vibecoding
统计学小王子11 小时前
数学建模国赛倒计时4天——《统计模型精讲(混合效应模型R语言实现)》
开发语言·数学建模·r语言
知无不研12 小时前
c语言中循环的介绍与简单应用
c语言·开发语言·算法·循环·for·while