介绍

使用无缓冲的通道来创建一个 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. Eclipse新建Maven中创建src文件夹报The folder is already a source folder错误解决办法

    问题: 解决办法:右击项目->Build Path->Configure Build Path选择(missing)文件夹remove,然后重新New Source Folder

  2. local feature和global feature的理解

    在计算机视觉方面,global feature是基于整张图像提取的特征,也就是说基于all pixels,常见的有颜色直方图.形状描述子.GIST等:local feature相对来说就是基于局部图像 ...

  3. POJ 1458:Common Subsequence

    Common Subsequence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 41957   Accepted: 16 ...

  4. maven集成SSM项目,Tomcat部署运行——SSM整合框架搭建(二)之问题

    问题一.当放开controller中的方法,出现如下问题 ### Error querying database. Cause: org.springframework.jdbc.CannotGetJ ...

  5. DataTable数据类型的一些操作 增加行、插入行、修改数据、修改列名、修改列顺序、计算、选取或删除行(列)、排序、某列distinct值 等

    Datatable 这个数据类型在C#中涉及到对数据库读取时的用处还是挺大的,最近在处理一个报表开发时,一开始把所有的操作都放在sql 上面来做,就是我需要什么样的数据我就query出什么,但是这样其 ...

  6. Flink 容错机制与状态

    简介 Apache Flink提供了一种容错机制,可以持续恢复数据流应用程序的状态. 该机制确保即使出现故障,经过恢复,程序的状态也会回到以前的状态. Flink 主持 at least once 语 ...

  7. maven工程运行演示

    通过maven提供的命令来运行maven工程,体会maven构建工程的优点. (1)运行web工程    进入maven工程目录(当前目录有pom.xml),运行tomcat:run命令 可能出现的问 ...

  8. mybatis初步配置容易出现的问题

    The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You ...

  9. filter滤镜兼容ie的rgba属性

    要在一个页面中设置一个半透明的白色div.这个貌似不是难题,只需要给这个div设置如下的属性即可: background: rgba(255,255,255,0.1); 但是要兼容到ie8.这个就有点 ...

  10. MySQL日志--二进制日志

    (一)什么是二进制日志 二进制日志(binlog)记录了数据库中所有的DDL和DML操作,但是不包括select语句,语句以"事件"的形式保存,记录了数据库的更改变化,在主从复制( ...