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

}
相关推荐
想摆烂的不会研究的研究生1 天前
每日八股——Redis(1)
数据库·经验分享·redis·后端·缓存
毕设源码-郭学长1 天前
【开题答辩全过程】以 基于SpringBoot技术的美妆销售系统为例,包含答辩的问题和答案
java·spring boot·后端
故事不长丨1 天前
C#正则表达式完全攻略:从基础到实战的全场景应用指南
开发语言·正则表达式·c#·regex
哈库纳玛塔塔1 天前
放弃 MyBatis,拥抱新一代 Java 数据访问库
java·开发语言·数据库·mybatis·orm·dbvisitor
追逐时光者1 天前
精选 10 款 .NET 开源免费、功能强大的 Windows 效率软件
后端·.net
追逐时光者1 天前
一款开源、免费的 WPF 自定义控件集
后端·.net
phltxy1 天前
从零入门JavaScript:基础语法全解析
开发语言·javascript
S***q3771 天前
Spring Boot管理用户数据
java·spring boot·后端
天“码”行空1 天前
java面向对象的三大特性之一多态
java·开发语言·jvm
毕设源码-郭学长1 天前
【开题答辩全过程】以 基于SpringBoot框架的民俗文化交流与交易平台的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端