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")}
	}

}
相关推荐
一朵梨花压海棠go3 分钟前
html+js实现表格本地筛选
开发语言·javascript·html·ecmascript
蒋星熠8 分钟前
Flutter跨平台工程实践与原理透视:从渲染引擎到高质产物
开发语言·python·算法·flutter·设计模式·性能优化·硬件工程
ChinaRainbowSea23 分钟前
7. LangChain4j + 记忆缓存详细说明
java·数据库·redis·后端·缓存·langchain·ai编程
舒一笑23 分钟前
同步框架与底层消费机制解决方案梳理
后端·程序员
minh_coo25 分钟前
Spring框架事件驱动架构核心注解之@EventListener
java·后端·spring·架构·intellij-idea
翻滚丷大头鱼33 分钟前
Java 集合Collection—List
java·开发语言
aramae1 小时前
C++ -- 模板
开发语言·c++·笔记·其他
胡耀超1 小时前
4、Python面向对象编程与模块化设计
开发语言·python·ai·大模型·conda·anaconda
索迪迈科技2 小时前
java后端工程师进修ing(研一版 || day40)
java·开发语言·学习·算法
白初&2 小时前
SpringBoot后端基础案例
java·spring boot·后端