展示如何使用无缓冲的通道创建一个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无缓冲通道实现工作池控制并发的更多相关文章

  1. golang channel无缓冲通道会发生阻塞的验证

    公司搞了午间技术par,本周我讲的主题是关于无缓冲通道channel是否会发生阻塞,并进行了验证. go语言中channel分为无缓冲通道和有缓冲通道两种 channel提供了一种在goroutine ...

  2. Golang并发编程有缓冲通道和无缓冲通道(channel)

    无缓冲通道 是指在接收前没有能力保存任何值得通道.这种类型的通道要求发送goroutine和接收goroutine同时准备好,才能完成发送和接收操作.如果两个goroutine没有同时准备好,通道会导 ...

  3. golang中为何在同一个goroutine中使用无缓冲通道会导致死锁

    package main import "fmt" func main() { /* 以下程序会导致死锁 c := make(chan int) c <- 10 n1 := ...

  4. Go语言的通道(1)-无缓冲通道

    前言: 上文中我们采用了[原子函数]已经[共享锁]两种方式分别对多个goroutine进行了同步,但是在go语言中提供了另一种更好的方式,那就是使用通道(Channel). 一.通道是什么? 其实无论 ...

  5. [GO]无缓冲通道(unbuffered channel)

    无缓冲通道(unbuffered channel)是指在接收前没有能力保存任何值的通道,在之前的例子中使用的都是无缓冲通道,需要注意的是,对于无缓冲通道而言,不管是往通道里写数据还是从通道里读数据,都 ...

  6. golang 无缓冲channel

    golang 无缓冲channel package main import "fmt" func main() { // 1S =1000ms //1ms = 1000us //1 ...

  7. go无缓冲通道

    package main import ( "fmt" "math/rand" "sync" "time" ) //wg ...

  8. Go语言有缓冲和无缓冲通道实现样例

    感觉可以,但不好用. 应该有封装程序更高的包包吧. package main import ( "math/rand" "fmt" "time&quo ...

  9. [Go] golang缓冲通道实现管理一组goroutine工作

    通道1.当一个资源需要在goroutine之间共享时,通道在goroutine之间架起了一个管道2.无缓冲通道和有缓冲通道,make的第二个参数就是缓冲区大小3.无缓冲通道需要发送和接收都准备好,否则 ...

随机推荐

  1. SElinux安全子系统---学习

    SElinux是一个强制访问控制的安全子系统,是为了让各个服务进程都受到约束,只能获取到属于自己的资源 SElinux有三种配置模式: 1:enforcing--强制启动安全配置策略,拦截不合法的请求 ...

  2. yarn的工作原理

    1.YARN 是什么? 从业界使用分布式系统的变化趋势和 hadoop 框架的长远发展来看,MapReduce的 JobTracker/TaskTracker 机制需要大规模的调整来修复它在可扩展性, ...

  3. JavaWeb学习路线

    一.三大组件介绍 javaweb在开发中有三大组件分别提供不同的功能,这三大组件为servlet,filter,listener 1.servlet 简单来说就是客户端请求服务器和接受服务器的响应,狭 ...

  4. 关于Java 去除空格,换行的代码

    public static String replaceBlank(String str) { String dest = ""; if (str != null) { //Pat ...

  5. tensorflow-变量

    #计数器 import tensorflow as tf state = tf.Variable(0,name='counter') #设定变量print(state.name) #打印变量one = ...

  6. JSON File Parse

    1.write a json file base on website(在网站上写一个json文件) json文件网址:https://raw.githubusercontent.com/DJOSIM ...

  7. JS基础整理

    使用JS的三种方式 1.直接在html标签中,使用事件属性,调用js代码 <button onclick="alert('弹框')">弹框!</button> ...

  8. 算法与数据结构(八) AOV网的关键路径(Swift版)

    上篇博客我们介绍了AOV网的拓扑序列,请参考<数据结构(七) AOV网的拓扑排序(Swift面向对象版)>.拓扑序列中包括项目的每个结点,沿着拓扑序列将项目进行下去是肯定可以将项目完成的, ...

  9. Java ActiveMQ 讲解(二)Spring ActiveMQ整合+注解消息监听

    对于ActiveMQ消息的发送,原声的api操作繁琐,而且如果不进行二次封装,打开关闭会话以及各种创建操作也是够够的了.那么,Spring提供了一个很方便的去收发消息的框架,spring jms.整合 ...

  10. MySQL数据备份方法

    MySQL的备份和还原 备份:副本    RAID1,RAID10:保证硬件损坏而不会业务中止:        DROP TABLE mydb.tb1; 备份类型:        热备份.温备份和冷备 ...