介绍

使用无缓冲的通道来创建一个 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

最新文章

  1. Android开发环境搭建之Eclipse/AndroidStudio
  2. java selenium针对多种情况的多窗口切换
  3. iOS-UIScrollView和UIPageControl的综合实力,滚动图,轮播图
  4. css3 文本记
  5. 第四十五篇、UITableViewCell高度计算
  6. 谈谈python 中__name__ = &#39;__main__&#39; 的作用
  7. JSON漫谈
  8. Egret 双端接入爱贝支付遇到的问题
  9. poi实现Excel导出
  10. 1148 - Mad Counting(数学)
  11. Java中代理对象的使用小结
  12. Webpack 2 视频教程 006 - 使用快捷方式进行编译
  13. java(11)带参数的方法
  14. Git常用命令及使用,GitLab/GitHub初探,Git/Svn区别
  15. Confluence 6 安装补丁类文件
  16. BootstrapValidator . select 必须选择一个 .callback . select .option
  17. kali linux wmtools安装
  18. python 实现int函数
  19. Python2.7-SciPy
  20. 对比网络模拟器软件——Cisco Packet Tracer、华为eNSP、H3C Cloud Lab

热门文章

  1. springboot指定配置文件运行
  2. linux桌面系统 镜像下载
  3. POJ - 3264 Balanced Lineup(线段树或RMQ)
  4. 干干净净的grep
  5. nodejs常用模块
  6. Flink 操作链与任务槽
  7. Linux用户管理 权限管理 内存管理 网络管理命令 (第四天)
  8. 【Android】家庭记账本手机版开发报告四
  9. HDU - 5695 Gym Class (优先队列+拓扑排序)
  10. WTL 选择文件