介绍

使用无缓冲的通道来创建一个 goroutine 池,这些 goroutine 执行并控制一组工作,让其并发执行。在这种情况下,使用无缓冲的通道要比随意指定一个缓冲区大小的有缓冲的通道好,因为这个情况下既不需要一个工作队列,也不需要一组 goroutine 配合执行。这种使用无缓冲的通道的方法允许使用者知道什么时候 goroutine 池正在执行工作,而且如果池里的所有goroutine 都忙,无法接受新的工作的时候,也能及时通过通道来通知调用者。使用无缓冲的通道不会有工作在队列里丢失或者卡住,所有工作都会被处理。

程序

work.go

package work

import (
"sync"
) //任务类型接口
type Worker interface {
Task(goid int)
} //任务池
type Pool struct {
work chan Worker
wg sync.WaitGroup
} //新建
func New(maxGoroutines int) *Pool {
//任务池
p := Pool{
work: make(chan Worker),
}
p.wg.Add(maxGoroutines)
//创建maxGoroutines个go协程
for i := 0; i < maxGoroutines; i++ {
go func(goid int) {
//保证goroutine不停止执行通道中的任务
for w := range p.work {
w.Task(goid)
}
//每个goroutine不再执行work通道中任务时停止
p.wg.Done()
}(i)
}
return &p
} //运行
func (p *Pool) Run(r Worker) {
p.work <- r
} //停止
func (p *Pool) Shutdown() {
close(p.work)
p.wg.Wait()
}

main.go

package main

import (
"gopro/patterns/work"
"log"
"sync"
"time"
) //
var names = []string{
"lili",
"yingying",
} //Worker实现类型
type namePrinter struct {
name string
} func (n *namePrinter) Task(goid int) {
log.Printf("goroutineID:%d,打印名字为:%s\n", goid, n.name)
time.Sleep(time.Second)
} func main() {
p := work.New(3)
var wg sync.WaitGroup
wg.Add(10 * len(names)) for i := 0; i < 10; i++ {
for _, name := range names {
//任务实例
np := namePrinter{
name: name,
} go func() {
p.Run(&np)
wg.Done()
}()
}
}
wg.Wait()
p.Shutdown()
}

执行结果

// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:yingying
// :: goroutineID:,打印名字为:yingying
// :: goroutineID:,打印名字为:yingying
// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:yingying
// :: goroutineID:,打印名字为:yingying
// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:yingying
// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:yingying
// :: goroutineID:,打印名字为:yingying
// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:yingying
// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:lili
// :: goroutineID:,打印名字为:yingying

Go语言-并发模式-goroutine池实例(work)的更多相关文章

  1. Go语言-并发模式-资源池实例(pool)

    Go语言并发模式 利用goroutine和channel进行go的并发模式,实现一个资源池实例(<Go语言实战>书中实例稍作修改) 资源池可以存储一定数量的资源,用户程序从资源池获取资源进 ...

  2. go语言】Goroutines 并发模式

    并发模式 让我们先来回顾一下boring函数的例子. func boring(msg string, c chan string) {    for i := 0; ; i++ {         c ...

  3. WCF实例上下文模式与并发模式对性能的影响

    实例上下文模式 InstanceContextMode 控制在响应客户端调用时,如何分配服务实例.InstanceContextMode 可以设置为以下值: •Single – 为所有客户端调用分配一 ...

  4. 《Go语言实战》摘录:7.2 并发模式 - pool

    7.2 并发模式 - pool

  5. 《Go语言实战》摘录:7.3 并发模式 - work

    7.3 并发模式 - work

  6. 《Go语言实战》摘录:7.1 并发模式 - runner

    7.1 并发模式 - runner

  7. 09. Go 语言并发

    Go 语言并发 并发指在同一时间内可以执行多个任务.并发编程含义比较广泛,包含多线程编程.多进程编程及分布式程序等.本章讲解的并发含义属于多线程编程. Go 语言通过编译器运行时(runtime),从 ...

  8. Go并发模式:管道与取消

    关键字:Go语言,管道,取消机制,并发,sync.WaitGroup,包引用,通道,defer,select GO并发模式:管道与取消 简介 Go的并发能力可以使构建一个流数据管道变得非常容易,并且可 ...

  9. Go语言并发机制

    Go语言中的并发 使用goroutine编程 使用 go 关键字用来创建 goroutine .将go声明放到一个需调用的函数之前,在相同地址空间调用运行这个函数,这样该函数执行时便会作为一个独立的并 ...

随机推荐

  1. C#获取屏幕分辨率率

    C#获取屏幕的分辨率   在C#中获取当前屏幕的分辨率的方法 1:rectangle类. 命名空间为:system.Drawing. system.Drawing.Rectangle rec=Scre ...

  2. 20170305深圳Meetup Rails中CSS,JS引用关系分析

    新手上路,若有错误请及时提醒 Rails中CSS,JS引用关系分析 一.Rails静态文件存放位置 二.Rails中CSS引用方式 三.Rails中JS引用方式与CSS类似 四.上面都是默认引用app ...

  3. js排序专场

    1,冒泡排序 function bubble(arr) { var len = arr.length - 1; for (let i = 0 ; i < len; i++) { var bool ...

  4. 安装redis cluster时:undefined method `invoke_with_build_args' for nil:NilClass

    gem install -l redis-3.3.3.gem ERROR: Loading command: install (LoadError) cannot load such file -- ...

  5. Typecho博客添加版权说明

    版权声明是指作品权利人对自己创作作品的权利的一种口头或书面声明,一般版权声明应该包括权利归属.作品使用准许方式.责任追究等方面的内容.诸如平时看文章时最后会有一个严禁转载的说明,其实这就是版权声明. ...

  6. 修改ssh主机名

    三台机器的配置相似,以zk1为例 1.修改hostname vi /etc/hostname zk1 2.修改hosts文件 vi /etc/hosts 10.45.48.233 zk1 10.45. ...

  7. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:SSM(Spring+Spring MVC+MyBatis)框架整合搭建详细步骤

    因为 Spring MVC 是 Spring 框架中的一个子模块,所以 Spring 与 SpringMVC 之间不存在整合的问题.实际上,SSM 框架的整合只涉及 Spring 与 MyBatis ...

  8. JAVA中序列化和反序列化中的静态成员问题

    关于这个标题的内容是面试笔试中比较常见的考题,大家跟随我的博客一起来学习下这个过程. ? ? JAVA中的序列化和反序列化主要用于: (1)将对象或者异常等写入文件,通过文件交互传输信息: (2)将对 ...

  9. PHP购物网站

    我使用的phpsteam经常用着用着就闪退,所以做起来挺麻烦的.里面的代码有抄袭借鉴网上的代码,就是那个php做购物网站点击量最高的那个. 但是我很多代码也是自己写的不和其相同. PHP是一门选修课, ...

  10. HDU 5285:wyh2000 and pupil

    wyh2000 and pupil  Accepts: 93  Submissions: 925  Time Limit: 3000/1500 MS (Java/Others)  Memory Lim ...