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

}
相关推荐
不做超级小白14 分钟前
JavaScript反爬技术解析与应对
开发语言·javascript·ecmascript
谢大旭30 分钟前
ASP.NET Core 中使用依赖注入 (DI) 容器获取并执行自定义服务
开发语言·后端·c#·asp.net
Libby博仙35 分钟前
asp.netcore 有关jwt的依赖包介绍
后端·c#·asp.net·.netcore
星如雨グッ!(๑•̀ㅂ•́)و✧1 小时前
Spring Boot 2 快速教程:WebFlux 集成 Mongodb(三)
spring boot·后端·mongodb
游王子1 小时前
Python NumPy(6):修改数组形状、翻转数组、修改数组维度
开发语言·python·numpy
我命由我123451 小时前
游戏引擎 Unity - Unity 设置为简体中文、Unity 创建项目
c语言·开发语言·c++·unity·visualstudio·c#·游戏引擎
fly spider2 小时前
每日 Java 面试题分享【第 20 天】
java·开发语言·面试·io
zhyhgx2 小时前
Maven
java·开发语言·maven
小松聊PHP进阶2 小时前
万字总结PHP与JavaScript、PHP与PHP 实现开箱即用的AES、RSA和较为安全的自定义加解密算法
前端·后端·php
美味小鱼3 小时前
Rust 数据类型详解:Scalar 与 Compound 类型
开发语言·后端·rust