[Go] golang无缓冲通道实现工作池控制并发
展示如何使用无缓冲的通道创建一个goroutine池,控制并发频率
1.无缓冲通道保证了两个goroutine之间的数据交换
2.当所有的goroutine都忙的时候,能够及时通过通道告知调用者
3.无缓冲的通道不会有工作在队列里丢失或卡住
4.创建一个工作池,比如这时候会创建出2个goroutine,被一个无缓冲通道阻塞住,等待在那里,除非通道关闭,在当前的gorotine上会无限循环读取通道,不会退出
5.当有一堆的任务goroutine被发送过来的时候,会先传送给那一个通道,这时候不管有多少个,都会阻塞并等待上面那俩工作完,就起到了控制并发的目的
- package main
- import (
- "log"
- "sync"
- "time"
- )
- //定义一个Worker接口,有个必须实现的Task()方法
- type Worker interface {
- Task()
- }
- //定义一个类型Pool,有两个成员
- type Pool struct {
- //成员work,通道类型,传递的是Worker类型
- work chan Worker
- //成员wg是计数信号量
- wg sync.WaitGroup
- }
- //定义New方法,返回的是Pool实例
- //传递的参数是goroutine池的数量
- func New(size int) *Pool {
- //实例化Pool类型
- pool := Pool{
- work: make(chan Worker),
- }
- //增加计数信号量
- pool.wg.Add(size)
- //使用循环创建多个goroutine
- for i := 0; i < size; i++ {
- //启动goroutine
- go func() {
- //从通道中获取值,这里如果没有会一直阻塞
- //这里会无限循环遍历,除非通道关闭了,否则不会跳出当前这个goroutine
- for w := range pool.work {
- //调用Worker类型的Task()方法
- w.Task()
- }
- }()
- pool.wg.Done()
- }
- return &pool
- }
- //给Pool类型定义Run方法
- //参数是Worker类型
- func (p *Pool) Run(w Worker) {
- //把Worker传进通道里
- p.work <- w
- }
- //给Pool类型定义 Shutdown方法
- func (p *Pool) Shutdown() {
- //关闭通道
- close(p.work)
- //等待所有goroutine执行结束
- p.wg.Wait()
- }
- //定义一个字符串数组
- var names = []string{
- "zhangsan",
- "lisi",
- "wangwu",
- }
- //定义一个类型namePrinter
- type namePrinter struct {
- //成员name ,字符串类型
- name string
- }
- //给类型实现Worker接口
- func (np *namePrinter) Task() {
- //打印namePrinter类型的name成员
- log.Printf(np.name)
- //睡眠一秒
- time.Sleep(time.Second)
- }
- func main() {
- //创建2个goroutine的池,因为通道是空的,这个地方有两个goroutine会阻塞在那
- pool := New(2)
- //定义计数信号量
- var wg sync.WaitGroup
- //增加计数,100次乘以数组元素个数
- wg.Add(100 * len(names))
- //循环100次,这个地方会瞬间生成300个goroutine,大并发的去执行任务
- for i := 0; i < 100; i++ {
- //循环数组
- for _, name := range names {
- //实例化namePrinter类型
- np := namePrinter{
- name: name,
- }
- //启动一个goroutine
- go func() {
- //调用Pool类型的run方法
- //传递的是Woker类型,因此要取地址
- //这里会把该Worker类型,发送到通道里,如果通道不为空,就会阻塞住
- //当300个goroutine,把name传递给run方法,会因为通道不为空被阻塞住
- //通道何时才能为空呢,也就只有在工作池里的goroutine把通道读走
- //因此会每次两个两个的打印,最多只会等待两个工作的完成
- pool.Run(&np)
- wg.Done()
- }()
- }
- }
- //等待上面的100次遍历结束
- wg.Wait()
- //停止工作池,关闭通道
- pool.Shutdown()
- }
[Go] golang无缓冲通道实现工作池控制并发的更多相关文章
- golang channel无缓冲通道会发生阻塞的验证
公司搞了午间技术par,本周我讲的主题是关于无缓冲通道channel是否会发生阻塞,并进行了验证. go语言中channel分为无缓冲通道和有缓冲通道两种 channel提供了一种在goroutine ...
- Golang并发编程有缓冲通道和无缓冲通道(channel)
无缓冲通道 是指在接收前没有能力保存任何值得通道.这种类型的通道要求发送goroutine和接收goroutine同时准备好,才能完成发送和接收操作.如果两个goroutine没有同时准备好,通道会导 ...
- golang中为何在同一个goroutine中使用无缓冲通道会导致死锁
package main import "fmt" func main() { /* 以下程序会导致死锁 c := make(chan int) c <- 10 n1 := ...
- Go语言的通道(1)-无缓冲通道
前言: 上文中我们采用了[原子函数]已经[共享锁]两种方式分别对多个goroutine进行了同步,但是在go语言中提供了另一种更好的方式,那就是使用通道(Channel). 一.通道是什么? 其实无论 ...
- [GO]无缓冲通道(unbuffered channel)
无缓冲通道(unbuffered channel)是指在接收前没有能力保存任何值的通道,在之前的例子中使用的都是无缓冲通道,需要注意的是,对于无缓冲通道而言,不管是往通道里写数据还是从通道里读数据,都 ...
- golang 无缓冲channel
golang 无缓冲channel package main import "fmt" func main() { // 1S =1000ms //1ms = 1000us //1 ...
- go无缓冲通道
package main import ( "fmt" "math/rand" "sync" "time" ) //wg ...
- Go语言有缓冲和无缓冲通道实现样例
感觉可以,但不好用. 应该有封装程序更高的包包吧. package main import ( "math/rand" "fmt" "time&quo ...
- [Go] golang缓冲通道实现管理一组goroutine工作
通道1.当一个资源需要在goroutine之间共享时,通道在goroutine之间架起了一个管道2.无缓冲通道和有缓冲通道,make的第二个参数就是缓冲区大小3.无缓冲通道需要发送和接收都准备好,否则 ...
随机推荐
- [LeetCode] Score of Parentheses 括号的分数
Given a balanced parentheses string S, compute the score of the string based on the following rule: ...
- 兼容IE8,滚动加载下一页
// 滚动加载下一页 var nowScrolledHeight = document.documentElement.scrollTop || document.body.scrol ...
- Mesos源码分析(15): Test Executor的运行
Test Executor的代码在src/examples/test_executor.cpp中 int main(int argc, char** argv) { TestExecutor ...
- 【开源项目】电视盒子好用又强大的APP: TVRemoteIME
TVRemoteIME 电视盒子的远程输入法应用,可跨屏远程输入.跨屏远程控制盒子.远程文件管理.HTTP/RTMP/MMS网络视频直播.ED2K/种子文件的视频文件边下边播 应用的诞生 自从家里有电 ...
- [Swift]LeetCode354. 俄罗斯套娃信封问题 | Russian Doll Envelopes
You have a number of envelopes with widths and heights given as a pair of integers (w, h). One envel ...
- [Swift]LeetCode500. 键盘行 | Keyboard Row
Given a List of words, return the words that can be typed using letters of alphabet on only one row' ...
- [Swift]LeetCode862. 和至少为 K 的最短子数组 | Shortest Subarray with Sum at Least K
Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K. If there ...
- [Swift]LeetCode899. 有序队列 | Orderly Queue
A string S of lowercase letters is given. Then, we may make any number of moves. In each move, we c ...
- PHP常用设计模式讲解
开发中适当的使用设计模式,可以让项目有更易扩展,易维护.低耦合,代码简洁等 单例模式 <?php /** * 单例模式:使类在全局范围内只允许创建一个对象,常用于数据库连接等 */ class ...
- Shell脚本中的for case while循环流程控制语句的使用
shell作为一种脚本编程语言,同样包含循环.分支等其他程序控制结构,从而轻松完成更加复杂.强大的功能. 编写脚本的思路 1 明确脚本的功能 2 编写脚本时会使用到那些命令 ? 3 把变化的 ...